Bug 1275507 - Part 2: New nsIUrlClassifierUtils function to create update request. r=francois draft
authorHenry Chang <hchang@mozilla.com>
Tue, 19 Jul 2016 18:10:12 +0800
changeset 389817 1f51aa85698fea27f358862705c726d05e41bafc
parent 389816 baea119d4ef8d40de79f5b6d84798f438bda3bc2
child 525862 354078b2d63c7f1e6eec11263ca4b918177f7105
push id23523
push userhchang@mozilla.com
push dateWed, 20 Jul 2016 03:58:22 +0000
reviewersfrancois
bugs1275507
milestone50.0a1
Bug 1275507 - Part 2: New nsIUrlClassifierUtils function to create update request. r=francois MozReview-Commit-ID: 3jUjfbkpTct
toolkit/components/url-classifier/nsIUrlClassifierUtils.idl
toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
toolkit/components/url-classifier/tests/unit/test_safebrowsing_protobuf.js
toolkit/components/url-classifier/tests/unit/xpcshell.ini
--- a/toolkit/components/url-classifier/nsIUrlClassifierUtils.idl
+++ b/toolkit/components/url-classifier/nsIUrlClassifierUtils.idl
@@ -43,9 +43,22 @@ interface nsIUrlClassifierUtils : nsISup
   /**
    * Convert list name to threat type.
    *
    * @param The list name.
    *
    * @returns The threat type in integer.
    */
   uint32_t convertListNameToThreatType(in ACString listName);
+
+  /**
+   * Make update request for given lists and their states.
+   *
+   * @param aListNames An array of list name represented in string.
+   * @param aState An array of states (in string) for each list.
+   * @param aCount The array length of aList and aState.
+   *
+   * @returns A string to store request. Not null-terminated.
+   */
+  ACString makeUpdateRequestV4([array, size_is(aCount)] in string aListNames,
+                               [array, size_is(aCount)] in string aStates,
+                               in uint32_t aCount);
 };
--- a/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
@@ -6,16 +6,17 @@
 #include "nsString.h"
 #include "nsIURI.h"
 #include "nsUrlClassifierUtils.h"
 #include "nsTArray.h"
 #include "nsReadableUtils.h"
 #include "plbase64.h"
 #include "prprf.h"
 #include "nsPrintfCString.h"
+#include "safebrowsing.pb.h"
 
 #define DEFAULT_PROTOCOL_VERSION "2.2"
 
 static char int_to_hex_digit(int32_t i)
 {
   NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit");
   return static_cast<char>(((i < 10) ? (i + '0') : ((i - 10) + 'A')));
 }
@@ -67,16 +68,88 @@ IsOctal(const nsACString & num)
     if (!isdigit(num[i]) || num[i] == '8' || num[i] == '9') {
       return false;
     }
   }
 
   return true;
 }
 
+/////////////////////////////////////////////////////////////////
+// SafeBrowsing V4 related utits.
+
+namespace mozilla {
+namespace safebrowsing {
+
+static PlatformType
+GetPlatformType()
+{
+#if defined(ANDROID)
+  return ANDROID_PLATFORM;
+#elif defined(XP_MACOSX)
+  return OSX_PLATFORM;
+#elif defined(XP_LINUX)
+  return LINUX_PLATFORM;
+#elif defined(XP_WIN)
+  return WINDOWS_PLATFORM;
+#else
+  #error Unrecognized platform type.
+#endif
+
+  return PLATFORM_TYPE_UNSPECIFIED;
+}
+
+typedef FetchThreatListUpdatesRequest_ListUpdateRequest ListUpdateRequest;
+typedef FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints Constraints;
+
+static void
+InitListUpdateRequest(ThreatType aThreatType,
+                      const char* aState,
+                      ListUpdateRequest* aListUpdateRequest)
+{
+  aListUpdateRequest->set_threat_type(aThreatType);
+  aListUpdateRequest->set_platform_type(GetPlatformType());
+  aListUpdateRequest->set_threat_entry_type(URL);
+
+  // Only RAW data is supported for now.
+  // TODO: Bug 1285848 Supports Rice-Golomb encoding.
+  Constraints* contraints = new Constraints();
+  contraints->add_supported_compressions(RAW);
+  aListUpdateRequest->set_allocated_constraints(contraints);
+
+  // Only set non-empty state.
+  if (aState[0] != '\0') {
+    aListUpdateRequest->set_state(aState);
+  }
+}
+
+static ClientInfo*
+CreateClientInfo()
+{
+  ClientInfo* c = new ClientInfo();
+
+  nsCOMPtr<nsIPrefBranch> prefBranch =
+    do_GetService(NS_PREFSERVICE_CONTRACTID);
+
+  nsXPIDLCString clientId;
+  nsresult rv = prefBranch->GetCharPref("browser.safebrowsing.id",
+                                        getter_Copies(clientId));
+
+  if (NS_FAILED(rv)) {
+    clientId = "Firefox"; // Use "Firefox" as fallback.
+  }
+
+  c->set_client_id(clientId.get());
+
+  return c;
+}
+
+} // end of namespace safebrowsing.
+} // end of namespace mozilla.
+
 nsUrlClassifierUtils::nsUrlClassifierUtils() : mEscapeCharmap(nullptr)
 {
 }
 
 nsresult
 nsUrlClassifierUtils::Init()
 {
   // Everything but alpha numerics, - and .
@@ -181,16 +254,50 @@ nsUrlClassifierUtils::GetProtocolVersion
       aVersion = NS_SUCCEEDED(rv) ? version : DEFAULT_PROTOCOL_VERSION;
   } else {
       aVersion = DEFAULT_PROTOCOL_VERSION;
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsUrlClassifierUtils::MakeUpdateRequestV4(const char** aListNames,
+                                          const char** aStates,
+                                          uint32_t aCount,
+                                          nsACString &aRequest)
+{
+  using namespace mozilla::safebrowsing;
+
+  FetchThreatListUpdatesRequest r;
+  r.set_allocated_client(CreateClientInfo());
+
+  for (uint32_t i = 0; i < aCount; i++) {
+    nsCString listName(aListNames[i]);
+    uint32_t threatType;
+    nsresult rv = ConvertListNameToThreatType(listName, &threatType);
+    if (NS_FAILED(rv)) {
+      continue; // Unknown list name.
+    }
+    auto lur = r.mutable_list_update_requests()->Add();
+    InitListUpdateRequest(static_cast<ThreatType>(threatType), aStates[i], lur);
+  }
+
+  // Then serialize.
+  std::string s;
+  r.SerializeToString(&s);
+
+  nsCString out;
+  out.Assign(s.c_str(), s.size());
+
+  aRequest = out;
+
+  return NS_OK;
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // non-interface methods
 
 nsresult
 nsUrlClassifierUtils::CanonicalizeHostname(const nsACString & hostname,
                                            nsACString & _retval)
 {
   nsAutoCString unescaped;
new file mode 100644
--- /dev/null
+++ b/toolkit/components/url-classifier/tests/unit/test_safebrowsing_protobuf.js
@@ -0,0 +1,23 @@
+function run_test() {
+  let urlUtils = Cc["@mozilla.org/url-classifier/utils;1"]
+                   .getService(Ci.nsIUrlClassifierUtils);
+
+  // No list at all.
+  let requestNoList = urlUtils.makeUpdateRequestV4([], [], 0);
+
+  // Only one valid list name.
+  let requestOneValid =
+    urlUtils.makeUpdateRequestV4(["goog-phish-proto"], ["AAAAAA"], 1);
+
+  // Only one invalid list name.
+  let requestOneInvalid =
+    urlUtils.makeUpdateRequestV4(["bad-list-name"], ["AAAAAA"], 1);
+
+  // One valid and one invalid list name.
+  let requestOneInvalidOneValid =
+    urlUtils.makeUpdateRequestV4(["goog-phish-proto", "bad-list-name"],
+                                 ["AAAAAA", "AAAAAA"], 2);
+
+  equal(requestNoList, requestOneInvalid);
+  equal(requestOneValid, requestOneInvalidOneValid);
+}
\ No newline at end of file
--- a/toolkit/components/url-classifier/tests/unit/xpcshell.ini
+++ b/toolkit/components/url-classifier/tests/unit/xpcshell.ini
@@ -16,8 +16,9 @@ support-files =
 [test_partial.js]
 [test_prefixset.js]
 [test_threat_type_conversion.js]
 [test_provider_url.js]
 [test_streamupdater.js]
 [test_digest256.js]
 [test_listmanager.js]
 [test_pref.js]
+[test_safebrowsing_protobuf.js]