Bug 1024610: Register tracking protection list and hook it up in nsChannelClassifier (r=gcp)
authorMonica Chew <mmc@mozilla.com>
Wed, 02 Jul 2014 12:41:00 -0700
changeset 191937 4e35172b6476f5378f45b3329353c9f9aa06615f
parent 191936 079d12b17a263c6117cecc4fb4a531b9641e9912
child 191938 f07db8ccaa2ff79fe9bc3255cd930762201ac882
push id45704
push usermchew@mozilla.com
push dateWed, 02 Jul 2014 19:42:33 +0000
treeherdermozilla-inbound@4e35172b6476 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgcp
bugs1024610
milestone33.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 1024610: Register tracking protection list and hook it up in nsChannelClassifier (r=gcp)
browser/components/safebrowsing/content/test/head.js
modules/libpref/src/init/all.js
toolkit/components/url-classifier/SafeBrowsing.jsm
toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
toolkit/components/url-classifier/nsUrlClassifierDBService.h
toolkit/components/url-classifier/tests/mochitest/test_classifier.html
toolkit/components/url-classifier/tests/mochitest/test_classifier_worker.html
xpcom/base/ErrorList.h
--- a/browser/components/safebrowsing/content/test/head.js
+++ b/browser/components/safebrowsing/content/test/head.js
@@ -1,5 +1,5 @@
 // Force SafeBrowsing to be initialized for the tests
-Services.prefs.setCharPref("urlclassifier.malware_table", "test-malware-simple");
-Services.prefs.setCharPref("urlclassifier.phish_table", "test-phish-simple");
+Services.prefs.setCharPref("urlclassifier.malwareTable", "test-malware-simple");
+Services.prefs.setCharPref("urlclassifier.phishTable", "test-phish-simple");
 SafeBrowsing.init();
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -814,16 +814,18 @@ pref("content.sink.pending_event_mode", 
 //   2 = openAbused
 pref("privacy.popups.disable_from_plugins", 2);
 
 // "do not track" HTTP header, disabled by default
 pref("privacy.donottrackheader.enabled",    false);
 //   0 = tracking is acceptable
 //   1 = tracking is unacceptable
 pref("privacy.donottrackheader.value",      1);
+// Enforce tracking protection
+pref("privacy.trackingprotection.enabled",  false);
 
 pref("dom.event.contextmenu.enabled",       true);
 pref("dom.event.clipboardevents.enabled",   true);
 #if defined(XP_WIN) && !defined(RELEASE_BUILD)
 pref("dom.event.highrestimestamp.enabled",  true);
 #else
 pref("dom.event.highrestimestamp.enabled",  false);
 #endif
@@ -4182,21 +4184,27 @@ pref("dom.voicemail.enabled", false);
 // Numeric default service id for Voice Mail API calls with |serviceId|
 // parameter omitted.
 pref("dom.voicemail.defaultServiceId", 0);
 
 // DOM Inter-App Communication API.
 pref("dom.inter-app-communication-api.enabled", false);
 
 // The tables used for Safebrowsing phishing and malware checks.
-pref("urlclassifier.malware_table", "goog-malware-shavar,test-malware-simple");
-pref("urlclassifier.phish_table", "goog-phish-shavar,test-phish-simple");
+pref("urlclassifier.malwareTable", "goog-malware-shavar,test-malware-simple");
+pref("urlclassifier.phishTable", "goog-phish-shavar,test-phish-simple");
 pref("urlclassifier.downloadBlockTable", "");
 pref("urlclassifier.downloadAllowTable", "");
-pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,goog-downloadwhite-digest256");
+pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,goog-downloadwhite-digest256,mozpub-track-digest256");
+
+// The table and update/gethash URLs for Safebrowsing phishing and malware
+// checks.
+pref("urlclassifier.trackingTable", "mozpub-track-digest256");
+pref("browser.trackingprotection.updateURL", "https://tracking.services.mozilla.com/update?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
+pref("browser.trackingprotection.gethashURL", "https://tracking.services.mozilla.com/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
 
 // Turn off Spatial navigation by default.
 pref("snav.enabled", false);
 
 // Turn off touch caret by default.
 pref("touchcaret.enabled", false);
 
 // Maximum distance to the center of touch caret (in app unit square) which
--- a/toolkit/components/url-classifier/SafeBrowsing.jsm
+++ b/toolkit/components/url-classifier/SafeBrowsing.jsm
@@ -19,20 +19,21 @@ function getLists(prefName) {
     return [];
   }
   return pref.split(",")
     .filter(function(value) { return value.indexOf("test-") == -1; })
     .map(function(value) { return value.trim(); });
 }
 
 // These may be a comma-separated lists of tables.
-const phishingLists = getLists("urlclassifier.phish_table");
-const malwareLists = getLists("urlclassifier.malware_table");
+const phishingLists = getLists("urlclassifier.phishTable");
+const malwareLists = getLists("urlclassifier.malwareTable");
 const downloadBlockLists = getLists("urlclassifier.downloadBlockTable");
 const downloadAllowLists = getLists("urlclassifier.downloadAllowTable");
+const trackingProtectionLists = getLists("urlclassifier.trackingTable");
 
 var debug = false;
 function log(...stuff) {
   if (!debug)
     return;
 
   let msg = "SafeBrowsing: " + stuff.join(" ");
   Services.console.logStringMessage(msg);
@@ -60,16 +61,21 @@ this.SafeBrowsing = {
       listManager.registerTable(malwareLists[i], this.updateURL, this.gethashURL);
     }
     for (let i = 0; i < downloadBlockLists.length; ++i) {
       listManager.registerTable(downloadBlockLists[i], this.updateURL, this.gethashURL);
     }
     for (let i = 0; i < downloadAllowLists.length; ++i) {
       listManager.registerTable(downloadAllowLists[i], this.updateURL, this.gethashURL);
     }
+    for (let i = 0; i < trackingProtectionLists.length; ++i) {
+      listManager.registerTable(trackingProtectionLists[i],
+                                this.trackingUpdateURL,
+                                this.trackingGethashURL);
+    }
     this.addMozEntries();
 
     this.controlUpdateChecking();
     this.initialized = true;
 
     log("init() finished");
   },
 
@@ -94,17 +100,18 @@ this.SafeBrowsing = {
   },
 
 
   readPrefs: function() {
     log("reading prefs");
 
     debug = Services.prefs.getBoolPref("browser.safebrowsing.debug");
     this.phishingEnabled = Services.prefs.getBoolPref("browser.safebrowsing.enabled");
-    this.malwareEnabled  = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
+    this.malwareEnabled = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
+    this.trackingEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.enabled");
     this.updateProviderURLs();
 
     // XXX The listManager backend gets confused if this is called before the
     // lists are registered. So only call it here when a pref changes, and not
     // when doing initialization. I expect to refactor this later, so pardon the hack.
     if (this.initialized)
       this.controlUpdateChecking();
   },
@@ -129,16 +136,20 @@ this.SafeBrowsing = {
     this.reportMalwareErrorURL = Services.urlFormatter.formatURLPref(basePref + "reportMalwareErrorURL");
 
     // Urls used to update DB
     this.updateURL  = Services.urlFormatter.formatURLPref(basePref + "updateURL");
     this.gethashURL = Services.urlFormatter.formatURLPref(basePref + "gethashURL");
 
     this.updateURL  = this.updateURL.replace("SAFEBROWSING_ID", clientID);
     this.gethashURL = this.gethashURL.replace("SAFEBROWSING_ID", clientID);
+    this.trackingUpdateURL = Services.urlFormatter.formatURLPref(
+      "browser.trackingprotection.updateURL");
+    this.trackingGethashURL = Services.urlFormatter.formatURLPref(
+      "browser.trackingprotection.gethashURL");
   },
 
   controlUpdateChecking: function() {
     log("phishingEnabled:", this.phishingEnabled, "malwareEnabled:", this.malwareEnabled);
 
     let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
                       getService(Ci.nsIUrlListManager);
 
@@ -165,16 +176,23 @@ this.SafeBrowsing = {
     }
     for (let i = 0; i < downloadAllowLists.length; ++i) {
       if (this.malwareEnabled) {
         listManager.enableUpdate(downloadAllowLists[i]);
       } else {
         listManager.disableUpdate(downloadAllowLists[i]);
       }
     }
+    for (let i = 0; i < trackingProtectionLists.length; ++i) {
+      if (this.trackingEnabled) {
+        listManager.enableUpdate(trackingProtectionLists[i]);
+      } else {
+        listManager.disableUpdate(trackingProtectionLists[i]);
+      }
+    }
   },
 
 
   addMozEntries: function() {
     // 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";
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -62,22 +62,26 @@ PRLogModuleInfo *gUrlClassifierDbService
 
 // Prefs for implementing nsIURIClassifier to block page loads
 #define CHECK_MALWARE_PREF      "browser.safebrowsing.malware.enabled"
 #define CHECK_MALWARE_DEFAULT   false
 
 #define CHECK_PHISHING_PREF     "browser.safebrowsing.enabled"
 #define CHECK_PHISHING_DEFAULT  false
 
+#define CHECK_TRACKING_PREF     "privacy.trackingprotection.enabled"
+#define CHECK_TRACKING_DEFAULT  false
+
 #define GETHASH_NOISE_PREF      "urlclassifier.gethashnoise"
 #define GETHASH_NOISE_DEFAULT   4
 
 // Comma-separated lists
-#define MALWARE_TABLE_PREF      "urlclassifier.malware_table"
-#define PHISH_TABLE_PREF        "urlclassifier.phish_table"
+#define MALWARE_TABLE_PREF      "urlclassifier.malwareTable"
+#define PHISH_TABLE_PREF        "urlclassifier.phishTable"
+#define TRACKING_TABLE_PREF     "urlclassifier.trackingTable"
 #define DOWNLOAD_BLOCK_TABLE_PREF "urlclassifier.downloadBlockTable"
 #define DOWNLOAD_ALLOW_TABLE_PREF "urlclassifier.downloadAllowTable"
 #define DISALLOW_COMPLETION_TABLE_PREF "urlclassifier.disallow_completions"
 
 #define CONFIRM_AGE_PREF        "urlclassifier.max-complete-age"
 #define CONFIRM_AGE_DEFAULT_SEC (45 * 60)
 
 class nsUrlClassifierDBServiceWorker;
@@ -845,17 +849,18 @@ nsUrlClassifierLookupCallback::LookupCom
                            PREFIX_SIZE);
 
         nsresult rv = completer->Complete(partialHash, gethashUrl, this);
         if (NS_SUCCEEDED(rv)) {
           mPendingCompletions++;
         }
       } else {
         // For tables with no hash completer, a complete hash match is
-        // good enough, we'll consider it fresh.
+        // good enough, we'll consider it fresh, even if it hasn't been updated
+        // in 45 minutes.
         if (result.Complete()) {
           result.mFresh = true;
         } else {
           NS_WARNING("Partial match in a table without a valid completer, ignoring partial match.");
         }
       }
     }
   }
@@ -991,56 +996,54 @@ nsUrlClassifierLookupCallback::HandleRes
 class nsUrlClassifierClassifyCallback MOZ_FINAL : public nsIUrlClassifierCallback
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIURLCLASSIFIERCALLBACK
 
   nsUrlClassifierClassifyCallback(nsIURIClassifierCallback *c,
                                   bool checkMalware,
-                                  bool checkPhishing)
+                                  bool checkPhishing,
+                                  bool checkTracking)
     : mCallback(c)
     , mCheckMalware(checkMalware)
     , mCheckPhishing(checkPhishing)
+    , mCheckTracking(checkTracking)
     {}
 
 private:
   ~nsUrlClassifierClassifyCallback() {}
 
   nsCOMPtr<nsIURIClassifierCallback> mCallback;
   bool mCheckMalware;
   bool mCheckPhishing;
+  bool mCheckTracking;
 };
 
 NS_IMPL_ISUPPORTS(nsUrlClassifierClassifyCallback,
                   nsIUrlClassifierCallback)
 
 NS_IMETHODIMP
 nsUrlClassifierClassifyCallback::HandleEvent(const nsACString& tables)
 {
   // XXX: we should probably have the wardens tell the service which table
   // names match with which classification.  For now the table names give
   // enough information.
   nsresult response = NS_OK;
 
-  nsACString::const_iterator begin, end;
-
-  tables.BeginReading(begin);
-  tables.EndReading(end);
   if (mCheckMalware &&
-      FindInReadable(NS_LITERAL_CSTRING("-malware-"), begin, end)) {
+      FindInReadable(NS_LITERAL_CSTRING("-malware-"), tables)) {
     response = NS_ERROR_MALWARE_URI;
-  } else {
-    // Reset begin before checking phishing table
-    tables.BeginReading(begin);
-
-    if (mCheckPhishing &&
-        FindInReadable(NS_LITERAL_CSTRING("-phish-"), begin, end)) {
-      response = NS_ERROR_PHISHING_URI;
-    }
+  } else if (mCheckPhishing &&
+    FindInReadable(NS_LITERAL_CSTRING("-phish-"), tables)) {
+    response = NS_ERROR_PHISHING_URI;
+  } else if (mCheckTracking &&
+    FindInReadable(NS_LITERAL_CSTRING("-track-"), tables)) {
+    LOG(("Blocking tracking uri [this=%p]", this));
+    response = NS_ERROR_TRACKING_URI;
   }
 
   mCallback->OnClassifyComplete(response);
 
   return NS_OK;
 }
 
 
@@ -1076,16 +1079,17 @@ nsUrlClassifierDBService::GetInstance(ns
   }
   return sUrlClassifierDBService;
 }
 
 
 nsUrlClassifierDBService::nsUrlClassifierDBService()
  : mCheckMalware(CHECK_MALWARE_DEFAULT)
  , mCheckPhishing(CHECK_PHISHING_DEFAULT)
+ , mCheckTracking(CHECK_TRACKING_DEFAULT)
  , mInUpdate(false)
 {
 }
 
 nsUrlClassifierDBService::~nsUrlClassifierDBService()
 {
   sUrlClassifierDBService = nullptr;
 }
@@ -1110,16 +1114,22 @@ nsUrlClassifierDBService::ReadTablesFrom
   }
 
   Preferences::GetCString(DOWNLOAD_ALLOW_TABLE_PREF, &tables);
   if (!tables.IsEmpty()) {
     allTables.Append(',');
     allTables.Append(tables);
   }
 
+  Preferences::GetCString(TRACKING_TABLE_PREF, &tables);
+  if (!tables.IsEmpty()) {
+    allTables.Append(',');
+    allTables.Append(tables);
+  }
+
   Classifier::SplitTables(allTables, mGethashTables);
 
   Preferences::GetCString(DISALLOW_COMPLETION_TABLE_PREF, &tables);
   Classifier::SplitTables(tables, mDisallowCompletionsTables);
 
   return NS_OK;
 }
 
@@ -1131,29 +1141,33 @@ nsUrlClassifierDBService::Init()
     gUrlClassifierDbServiceLog = PR_NewLogModule("UrlClassifierDbService");
 #endif
 
   // Retrieve all the preferences.
   mCheckMalware = Preferences::GetBool(CHECK_MALWARE_PREF,
     CHECK_MALWARE_DEFAULT);
   mCheckPhishing = Preferences::GetBool(CHECK_PHISHING_PREF,
     CHECK_PHISHING_DEFAULT);
+  mCheckTracking = Preferences::GetBool(CHECK_TRACKING_PREF,
+    CHECK_TRACKING_DEFAULT);
   uint32_t gethashNoise = Preferences::GetUint(GETHASH_NOISE_PREF,
     GETHASH_NOISE_DEFAULT);
   gFreshnessGuarantee = Preferences::GetInt(CONFIRM_AGE_PREF,
     CONFIRM_AGE_DEFAULT_SEC);
   ReadTablesFromPrefs();
 
   // Do we *really* need to be able to change all of these at runtime?
   Preferences::AddStrongObserver(this, CHECK_MALWARE_PREF);
   Preferences::AddStrongObserver(this, CHECK_PHISHING_PREF);
+  Preferences::AddStrongObserver(this, CHECK_TRACKING_PREF);
   Preferences::AddStrongObserver(this, GETHASH_NOISE_PREF);
   Preferences::AddStrongObserver(this, CONFIRM_AGE_PREF);
   Preferences::AddStrongObserver(this, PHISH_TABLE_PREF);
   Preferences::AddStrongObserver(this, MALWARE_TABLE_PREF);
+  Preferences::AddStrongObserver(this, TRACKING_TABLE_PREF);
   Preferences::AddStrongObserver(this, DOWNLOAD_BLOCK_TABLE_PREF);
   Preferences::AddStrongObserver(this, DOWNLOAD_ALLOW_TABLE_PREF);
   Preferences::AddStrongObserver(this, DISALLOW_COMPLETION_TABLE_PREF);
 
   // Force PSM loading on main thread
   nsresult rv;
   nsCOMPtr<nsICryptoHash> acryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1207,32 +1221,40 @@ nsUrlClassifierDBService::Classify(nsIPr
   NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
 
   if (!(mCheckMalware || mCheckPhishing)) {
     *result = false;
     return NS_OK;
   }
 
   nsRefPtr<nsUrlClassifierClassifyCallback> callback =
-    new nsUrlClassifierClassifyCallback(c, mCheckMalware, mCheckPhishing);
+    new nsUrlClassifierClassifyCallback(c, mCheckMalware, mCheckPhishing,
+                                        mCheckTracking);
   if (!callback) return NS_ERROR_OUT_OF_MEMORY;
 
   nsAutoCString tables;
   nsAutoCString malware;
   // LookupURI takes a comma-separated list already.
   Preferences::GetCString(MALWARE_TABLE_PREF, &malware);
   if (!malware.IsEmpty()) {
     tables.Append(malware);
   }
   nsAutoCString phishing;
   Preferences::GetCString(PHISH_TABLE_PREF, &phishing);
   if (!phishing.IsEmpty()) {
     tables.Append(',');
     tables.Append(phishing);
   }
+  nsAutoCString tracking;
+  Preferences::GetCString(TRACKING_TABLE_PREF, &tracking);
+  if (!tracking.IsEmpty()) {
+    LOG(("Looking up in tracking table, [cb=%p]", callback.get()));
+    tables.Append(',');
+    tables.Append(tracking);
+  }
   nsresult rv = LookupURI(aPrincipal, tables, callback, false, result);
   if (rv == NS_ERROR_MALFORMED_URI) {
     *result = false;
     // The URI had no hostname, don't try to classify it.
     return NS_OK;
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1475,19 +1497,23 @@ nsUrlClassifierDBService::Observe(nsISup
     nsCOMPtr<nsIPrefBranch> prefs(do_QueryInterface(aSubject, &rv));
     NS_ENSURE_SUCCESS(rv, rv);
     if (NS_LITERAL_STRING(CHECK_MALWARE_PREF).Equals(aData)) {
       mCheckMalware = Preferences::GetBool(CHECK_MALWARE_PREF,
         CHECK_MALWARE_DEFAULT);
     } else if (NS_LITERAL_STRING(CHECK_PHISHING_PREF).Equals(aData)) {
       mCheckPhishing = Preferences::GetBool(CHECK_PHISHING_PREF,
         CHECK_PHISHING_DEFAULT);
+    } else if (NS_LITERAL_STRING(CHECK_TRACKING_PREF).Equals(aData)) {
+      mCheckTracking = Preferences::GetBool(CHECK_TRACKING_PREF,
+        CHECK_TRACKING_DEFAULT);
     } else if (
       NS_LITERAL_STRING(PHISH_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(MALWARE_TABLE_PREF).Equals(aData) ||
+      NS_LITERAL_STRING(TRACKING_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(DOWNLOAD_BLOCK_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(DOWNLOAD_ALLOW_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(DISALLOW_COMPLETION_TABLE_PREF).Equals(aData)) {
       // Just read everything again.
       ReadTablesFromPrefs();
     } else if (NS_LITERAL_STRING(CONFIRM_AGE_PREF).Equals(aData)) {
       gFreshnessGuarantee = Preferences::GetInt(CONFIRM_AGE_PREF,
         CONFIRM_AGE_DEFAULT_SEC);
@@ -1512,18 +1538,20 @@ nsUrlClassifierDBService::Shutdown()
     return NS_OK;
 
   mCompleters.Clear();
 
   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (prefs) {
     prefs->RemoveObserver(CHECK_MALWARE_PREF, this);
     prefs->RemoveObserver(CHECK_PHISHING_PREF, this);
+    prefs->RemoveObserver(CHECK_TRACKING_PREF, this);
     prefs->RemoveObserver(PHISH_TABLE_PREF, this);
     prefs->RemoveObserver(MALWARE_TABLE_PREF, this);
+    prefs->RemoveObserver(TRACKING_TABLE_PREF, this);
     prefs->RemoveObserver(DOWNLOAD_BLOCK_TABLE_PREF, this);
     prefs->RemoveObserver(DOWNLOAD_ALLOW_TABLE_PREF, this);
     prefs->RemoveObserver(DISALLOW_COMPLETION_TABLE_PREF, this);
     prefs->RemoveObserver(CONFIRM_AGE_PREF, this);
   }
 
   DebugOnly<nsresult> rv;
   // First close the db connection.
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.h
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.h
@@ -94,16 +94,20 @@ private:
   // TRUE if the nsURIClassifier implementation should check for malware
   // uris on document loads.
   bool mCheckMalware;
 
   // TRUE if the nsURIClassifier implementation should check for phishing
   // uris on document loads.
   bool mCheckPhishing;
 
+  // TRUE if the nsURIClassifier implementation should check for tracking
+  // uris on document loads.
+  bool mCheckTracking;
+
   // TRUE if a BeginUpdate() has been called without an accompanying
   // CancelUpdate()/FinishUpdate().  This is used to prevent competing
   // updates, not to determine whether an update is still being
   // processed.
   bool mInUpdate;
 
   // The list of tables that can use the default hash completer object.
   nsTArray<nsCString> mGethashTables;
--- a/toolkit/components/url-classifier/tests/mochitest/test_classifier.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier.html
@@ -56,18 +56,18 @@ function doUpdate(update) {
   dbService.beginUpdate(listener, "test-malware-simple", "");
   dbService.beginStream("", "");
   dbService.updateStream(update);
   dbService.finishStream();
   dbService.finishUpdate();
 }
 
 SpecialPowers.pushPrefEnv(
-  {"set" : [["urlclassifier.malware_table", "test-malware-simple"],
-            ["urlclassifier.phish_table", "test-phish-simple"]]},
+  {"set" : [["urlclassifier.malwareTable", "test-malware-simple"],
+            ["urlclassifier.phishTable", "test-phish-simple"]]},
   function() { doUpdate(testUpdate); });
 
 // Expected finish() call is in "classifierFrame.html".
 SimpleTest.waitForExplicitFinish();
 
 </script>
 
 </pre>
--- a/toolkit/components/url-classifier/tests/mochitest/test_classifier_worker.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier_worker.html
@@ -68,18 +68,18 @@ function onmessage(event)
     SimpleTest.finish();
     return;
   }
 
   is(pieces[0], "success", pieces[1]);
 }
 
 SpecialPowers.pushPrefEnv(
-  {"set" : [["urlclassifier.malware_table", "test-malware-simple"],
-            ["urlclassifier.phish_table", "test-phish-simple"]]},
+  {"set" : [["urlclassifier.malwareTable", "test-malware-simple"],
+            ["urlclassifier.phishTable", "test-phish-simple"]]},
   function() { doUpdate(testUpdate); });
 
 window.addEventListener("message", onmessage, false);
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
 
--- a/xpcom/base/ErrorList.h
+++ b/xpcom/base/ErrorList.h
@@ -659,16 +659,17 @@
   /* 24: NS_ERROR_MODULE_URILOADER */
   /* ======================================================================= */
 #define MODULE NS_ERROR_MODULE_URILOADER
   ERROR(NS_ERROR_WONT_HANDLE_CONTENT,   FAILURE(1)),
   /* The load has been cancelled because it was found on a malware or phishing
    * blacklist. */
   ERROR(NS_ERROR_MALWARE_URI,           FAILURE(30)),
   ERROR(NS_ERROR_PHISHING_URI,          FAILURE(31)),
+  ERROR(NS_ERROR_TRACKING_URI,          FAILURE(34)),
   /* Used when "Save Link As..." doesn't see the headers quickly enough to
    * choose a filename.  See nsContextMenu.js. */
   ERROR(NS_ERROR_SAVE_LINK_AS_TIMEOUT,  FAILURE(32)),
   /* Used when the data from a channel has already been parsed and cached so it
    * doesn't need to be reparsed from the original source. */
   ERROR(NS_ERROR_PARSED_DATA_CACHED,    FAILURE(33)),
 
   /* This success code indicates that a refresh header was found and