Bug 837202: Add telemetry for application reputation check (r=paolo,yoric)
authorMonica Chew <mmc@mozilla.com>
Thu, 12 Dec 2013 11:20:11 -0800
changeset 160477 7aaf8db2d681e4b567fbc559a82de4d06c3ad9ed
parent 160476 020dcff94f4b29172ae3a57833b09ad24fc8c94d
child 160478 23abb5ffcfca4482f359a76546295c383ffdf083
push id25834
push userphilringnalda@gmail.com
push dateSun, 15 Dec 2013 02:20:53 +0000
treeherdermozilla-central@9fcc6330dc69 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspaolo, yoric
bugs837202
milestone29.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 837202: Add telemetry for application reputation check (r=paolo,yoric)
toolkit/components/downloads/ApplicationReputation.cpp
toolkit/components/telemetry/Histograms.json
--- a/toolkit/components/downloads/ApplicationReputation.cpp
+++ b/toolkit/components/downloads/ApplicationReputation.cpp
@@ -16,28 +16,30 @@
 #include "nsIStreamListener.h"
 #include "nsIStringStream.h"
 #include "nsIUploadChannel2.h"
 #include "nsIURI.h"
 #include "nsIUrlClassifierDBService.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
+#include "mozilla/Telemetry.h"
 
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsNetCID.h"
 #include "nsReadableUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMStrings.h"
 
 using mozilla::Preferences;
+using mozilla::Telemetry::Accumulate;
 
 // Preferences that we need to initialize the query. We may need another
 // preference than browser.safebrowsing.malware.enabled, or simply use
 // browser.safebrowsing.appRepURL. See bug 887041.
 #define PREF_SB_APP_REP_URL "browser.safebrowsing.appRepURL"
 #define PREF_SB_MALWARE_ENABLED "browser.safebrowsing.malware.enabled"
 #define PREF_GENERAL_LOCALE "general.useragent.locale"
 #define PREF_DOWNLOAD_BLOCK_TABLE "urlclassifier.download_block_table"
@@ -56,16 +58,37 @@ public:
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIURLCLASSIFIERCALLBACK
   PendingLookup(nsIApplicationReputationQuery* aQuery,
                 nsIApplicationReputationCallback* aCallback);
   ~PendingLookup();
 
 private:
+  /**
+   * Telemetry states.
+   */
+  /**
+   * The download appeared on the allowlist, blocklist, or no list (and thus
+   * could trigger a remote query).
+   */
+  enum LIST_TYPES {
+    ALLOW_LIST = 0,
+    BLOCK_LIST = 1,
+    NO_LIST = 2,
+  };
+  /**
+   * Status of the remote response (valid or not).
+   */
+  enum SERVER_RESPONSE_TYPES {
+    SERVER_RESPONSE_VALID = 0,
+    SERVER_RESPONSE_FAILED = 1,
+    SERVER_RESPONSE_INVALID = 2,
+  };
+
   nsCOMPtr<nsIApplicationReputationQuery> mQuery;
   nsCOMPtr<nsIApplicationReputationCallback> mCallback;
   /**
    * The response from the application reputation query. This is read in chunks
    * as part of our nsIStreamListener implementation and may contain embedded
    * NULLs.
    */
   nsCString mResponse;
@@ -100,39 +123,44 @@ PendingLookup::PendingLookup(nsIApplicat
   mCallback(aCallback) {
 }
 
 PendingLookup::~PendingLookup() {
 }
 
 nsresult
 PendingLookup::OnComplete(bool shouldBlock, nsresult rv) {
+  Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SHOULD_BLOCK,
+    shouldBlock);
   nsresult res = mCallback->OnComplete(shouldBlock, rv);
   return res;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsIUrlClassifierCallback
 NS_IMETHODIMP
 PendingLookup::HandleEvent(const nsACString& tables) {
   // HandleEvent is guaranteed to call the callback if either the URL can be
   // classified locally, or if there is an error sending the remote lookup.
   // Allow listing trumps block listing.
   nsCString allow_list;
   Preferences::GetCString(PREF_DOWNLOAD_ALLOW_TABLE, &allow_list);
   if (FindInReadable(tables, allow_list)) {
+    Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_LOCAL, ALLOW_LIST);
     return OnComplete(false, NS_OK);
   }
 
   nsCString block_list;
   Preferences::GetCString(PREF_DOWNLOAD_BLOCK_TABLE, &block_list);
   if (FindInReadable(tables, block_list)) {
+    Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_LOCAL, BLOCK_LIST);
     return OnComplete(true, NS_OK);
   }
 
+  Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_LOCAL, NO_LIST);
 #if 0
   nsresult rv = SendRemoteQuery();
   if (NS_FAILED(rv)) {
     return OnComplete(false, rv);
   }
   return NS_OK;
 #else
   // Revert when remote lookups are enabled (bug 933432)
@@ -263,38 +291,58 @@ PendingLookup::OnStopRequest(nsIRequest 
   return rv;
 }
 
 nsresult
 PendingLookup::OnStopRequestInternal(nsIRequest *aRequest,
                                      nsISupports *aContext,
                                      nsresult aResult,
                                      bool* aShouldBlock) {
+  if (NS_FAILED(aResult)) {
+    Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
+      SERVER_RESPONSE_FAILED);
+    return aResult;
+  }
+
   *aShouldBlock = false;
   nsresult rv;
   nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(aRequest, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
+      SERVER_RESPONSE_FAILED);
+    return rv;
+  }
 
   uint32_t status = 0;
   rv = channel->GetResponseStatus(&status);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
+      SERVER_RESPONSE_FAILED);
+    return rv;
+  }
 
   if (status != 200) {
+    Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
+      SERVER_RESPONSE_FAILED);
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   std::string buf(mResponse.Data(), mResponse.Length());
   safe_browsing::ClientDownloadResponse response;
   if (!response.ParseFromString(buf)) {
     NS_WARNING("Could not parse protocol buffer");
+    Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
+                                   SERVER_RESPONSE_INVALID);
     return NS_ERROR_CANNOT_CONVERT_DATA;
   }
 
   // There are several more verdicts, but we only respect one for now and treat
   // everything else as SAFE.
+  Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
+    SERVER_RESPONSE_VALID);
   if (response.verdict() == safe_browsing::ClientDownloadResponse::DANGEROUS) {
     *aShouldBlock = true;
   }
 
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS1(ApplicationReputationService,
@@ -330,16 +378,17 @@ ApplicationReputationService::~Applicati
 
 NS_IMETHODIMP
 ApplicationReputationService::QueryReputation(
     nsIApplicationReputationQuery* aQuery,
     nsIApplicationReputationCallback* aCallback) {
   NS_ENSURE_ARG_POINTER(aQuery);
   NS_ENSURE_ARG_POINTER(aCallback);
 
+  Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_COUNT, true);
   nsresult rv = QueryReputationInternal(aQuery, aCallback);
   if (NS_FAILED(rv)) {
     aCallback->OnComplete(false, rv);
   }
   return NS_OK;
 }
 
 nsresult ApplicationReputationService::QueryReputationInternal(
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -18,16 +18,34 @@
   },
   "A11Y_UPDATE_TIME": {
     "kind": "exponential",
     "high": "10000",
     "n_buckets": 50,
     "extended_statistics_ok": true,
     "description": "time spent updating accessibility (ms)"
   },
+  "APPLICATION_REPUTATION_SHOULD_BLOCK": {
+    "kind": "boolean",
+    "description": "Application reputation verdict (shouldBlock=false is OK)"
+  },
+  "APPLICATION_REPUTATION_LOCAL": {
+    "kind": "enumerated",
+    "n_values": 3,
+    "description": "Application reputation local results (0=ALLOW, 1=BLOCK, 2=NONE)"
+  },
+  "APPLICATION_REPUTATION_SERVER": {
+    "kind": "enumerated",
+    "n_values": 3,
+    "description": "Application reputation remote status (0 = OK, 1 = FAIL, 2 = INVALID)"
+  },
+  "APPLICATION_REPUTATION_COUNT": {
+    "kind": "flag",
+    "description": "Application reputation query count (both local and remote)"
+  },
   "BACKGROUNDFILESAVER_THREAD_COUNT": {
     "kind": "enumerated",
     "n_values": 21,
     "description": "Maximum number of concurrent threads reached during a given download session"
   },
   "COMPARTMENT_DONATED_NODE": {
     "kind": "boolean",
     "description": "When a compartment is destroyed, we record whether one of its nodes was ever adopted into another compartment"