Bug 1301008 - Pass safebrowsing v4 list state in base64 format to avoid truncation. draft
authorHenry Chang <hchang@mozilla.com>
Wed, 07 Sep 2016 17:45:15 +0800
changeset 410964 a3fe1d22803c9bf0b2eba95dae91710c83177ef7
parent 410066 8c9c4e816e86f903c1d820f3f29715dc070a5a4a
child 530642 993047eaaa932798d127b18bfdaec83be00de386
push id28803
push userhchang@mozilla.com
push dateWed, 07 Sep 2016 09:45:07 +0000
bugs1301008
milestone51.0a1
Bug 1301008 - Pass safebrowsing v4 list state in base64 format to avoid truncation. MozReview-Commit-ID: 6oVdQvEoMm2
toolkit/components/url-classifier/content/listmanager.js
toolkit/components/url-classifier/nsIUrlClassifierUtils.idl
toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
toolkit/components/url-classifier/tests/unit/test_listmanager.js
--- a/toolkit/components/url-classifier/content/listmanager.js
+++ b/toolkit/components/url-classifier/content/listmanager.js
@@ -396,17 +396,17 @@ PROT_ListManager.prototype.makeUpdateReq
     // never been downloaded. See Bug 1287058 for supporting
     // partial update.
     let stateArray = [];
     tableArray.forEach(listName => {
       // See Bug 1287059. We save the state to prefs until we support
       // "saving states to HashStore".
       let statePrefName = "browser.safebrowsing.provider.google4.state." + listName;
       let stateBase64 = this.prefs_.getPref(statePrefName, "");
-      stateArray.push(stateBase64 ? atob(stateBase64) : "");
+      stateArray.push(stateBase64);
     });
 
     let urlUtils = Cc["@mozilla.org/url-classifier/utils;1"]
                      .getService(Ci.nsIUrlClassifierUtils);
     let requestPayload =  urlUtils.makeUpdateRequestV4(tableArray,
                                                        stateArray,
                                                        tableArray.length);
     // Use a base64-encoded request.
--- a/toolkit/components/url-classifier/nsIUrlClassifierUtils.idl
+++ b/toolkit/components/url-classifier/nsIUrlClassifierUtils.idl
@@ -49,17 +49,17 @@ interface nsIUrlClassifierUtils : nsISup
    * @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 aState An array of states (encoded in base64 format) 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,
+                               [array, size_is(aCount)] in string aStatesBase64,
                                in uint32_t aCount);
 };
--- a/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
@@ -95,32 +95,36 @@ GetPlatformType()
 #endif
 }
 
 typedef FetchThreatListUpdatesRequest_ListUpdateRequest ListUpdateRequest;
 typedef FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints Constraints;
 
 static void
 InitListUpdateRequest(ThreatType aThreatType,
-                      const char* aState,
+                      const char* aStateBase64,
                       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);
+  if (aStateBase64[0] != '\0') {
+    nsCString stateBinary;
+    nsresult rv = Base64Decode(nsCString(aStateBase64), stateBinary);
+    if (NS_SUCCEEDED(rv)) {
+      aListUpdateRequest->set_state(stateBinary.get());
+    }
   }
 }
 
 static ClientInfo*
 CreateClientInfo()
 {
   ClientInfo* c = new ClientInfo();
 
@@ -262,34 +266,34 @@ nsUrlClassifierUtils::GetProtocolVersion
       aVersion = DEFAULT_PROTOCOL_VERSION;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsUrlClassifierUtils::MakeUpdateRequestV4(const char** aListNames,
-                                          const char** aStates,
+                                          const char** aStatesBase64,
                                           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);
+    InitListUpdateRequest(static_cast<ThreatType>(threatType), aStatesBase64[i], lur);
   }
 
   // Then serialize.
   std::string s;
   r.SerializeToString(&s);
 
   nsCString out;
   out.Assign(s.c_str(), s.size());
--- a/toolkit/components/url-classifier/tests/unit/test_listmanager.js
+++ b/toolkit/components/url-classifier/tests/unit/test_listmanager.js
@@ -149,17 +149,17 @@ add_test(function test_partialUpdateV4()
   disableAllUpdates();
 
   gListManager.enableUpdate(TEST_TABLE_DATA_V4.tableName);
 
   // Since the new client state has been responded and saved in
   // test_update_all_tables, this update request should send
   // a partial update to the server.
   let requestV4 = gUrlUtils.makeUpdateRequestV4([TEST_TABLE_DATA_V4.tableName],
-                                                [NEW_CLIENT_STATE],
+                                                [btoa(NEW_CLIENT_STATE)],
                                                 1);
   gExpectedQueryV4 = "&$req=" + btoa(requestV4);
 
   forceTableUpdate();
 });
 
 // Tests nsIUrlListManager.getGethashUrl.
 add_test(function test_getGethashUrl() {
@@ -306,34 +306,22 @@ function readFileToString(aFilename) {
   let f = do_get_file(aFilename);
   let stream = Cc["@mozilla.org/network/file-input-stream;1"]
     .createInstance(Ci.nsIFileInputStream);
   stream.init(f, -1, 0, 0);
   let buf = NetUtil.readInputStreamToString(stream, stream.available());
   return buf;
 }
 
-function buildUpdateRequestV4InBase64() {
-
-  let request =  urlUtils.makeUpdateRequestV4([TEST_TABLE_DATA_V4.tableName],
-                                              [""],
-                                              1);
-  return btoa(request);
-}
-
 function waitUntilStateSavedToPref(expectedState, callback) {
   const STATE_PREF_NAME_PREFIX = 'browser.safebrowsing.provider.google4.state.';
 
   let stateBase64 = '';
 
   try {
-    // The reason we get pref from 'googpub-phish-proto' instead of
-    // 'test-phish-proto' is 'googpub-phish-proto' would be returned
-    // while we look up the list name from SOCIAL_ENGINEERING_PUBLIC.
-    // See nsUrlClassifierUtils::THREAT_TYPE_CONV_TABLE.
     stateBase64 =
       prefBranch.getCharPref(STATE_PREF_NAME_PREFIX + 'test-phish-proto');
   } catch (e) {}
 
   if (stateBase64 === btoa(expectedState)) {
     do_print('State has been saved to pref!');
     callback();
     return;