Bug 1493563 - Part 7: Store the log more compactly, and cap the size of the origin log at a maximum limit adjustable by a pref; r=baku
☠☠ backed out by 1681bd622c63 ☠ ☠
authorEhsan Akhgari <ehsan@mozilla.com>
Sun, 23 Sep 2018 01:32:16 -0400
changeset 494518 bb2720a401fed1848e792b202d744171a60af7d5
parent 494517 ce0211be57a17fc1568f7b668d612a142014ff39
child 494519 3ef707008502d3555d384f8803b97d4b4c7a0d55
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1493563
milestone64.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 1493563 - Part 7: Store the log more compactly, and cap the size of the origin log at a maximum limit adjustable by a pref; r=baku Differential Revision: https://phabricator.services.mozilla.com/D6597
dom/base/ContentBlockingLog.h
modules/libpref/init/StaticPrefList.h
uriloader/base/nsIWebProgressListener.idl
--- a/dom/base/ContentBlockingLog.h
+++ b/dom/base/ContentBlockingLog.h
@@ -3,31 +3,37 @@
 /* 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/. */
 
 #ifndef mozilla_dom_ContentBlockingLog_h
 #define mozilla_dom_ContentBlockingLog_h
 
 #include "mozilla/JSONWriter.h"
-#include "mozilla/Pair.h"
+#include "mozilla/StaticPrefs.h"
 #include "mozilla/UniquePtr.h"
 #include "nsClassHashtable.h"
 #include "nsHashKeys.h"
 #include "nsReadableUtils.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 
 class ContentBlockingLog final
 {
-  // Each element is a pair of (type, blocked). The type values come from the
-  // blocking types defined in nsIWebProgressListener.
-  typedef nsTArray<mozilla::Pair<uint32_t, bool>> OriginLog;
+  struct LogEntry {
+    uint32_t mType;
+    uint32_t mRepeatCount;
+    bool mBlocked;
+  };
+
+  // Each element is a tuple of (type, blocked, repeatCount). The type values
+  // come from the blocking types defined in nsIWebProgressListener.
+  typedef nsTArray<LogEntry> OriginLog;
 
   struct StringWriteFunc : public JSONWriteFunc
   {
     nsAString& mBuffer; // The lifetime of the struct must be bound to the buffer
     explicit StringWriteFunc(nsAString& aBuffer)
       : mBuffer(aBuffer)
     {}
 
@@ -43,21 +49,36 @@ public:
 
   void RecordLog(const nsAString& aOrigin, uint32_t aType, bool aBlocked)
   {
     if (aOrigin.IsVoid()) {
       return;
     }
     auto entry = mLog.LookupForAdd(aOrigin);
     if (entry) {
-      entry.Data()->AppendElement(mozilla::MakePair(aType, aBlocked));
+      auto& log = entry.Data();
+      if (!log->IsEmpty()) {
+        auto& last = log->LastElement();
+        if (last.mType == aType &&
+            last.mBlocked == aBlocked) {
+          ++last.mRepeatCount;
+          // Don't record recorded events.  This helps compress our log.
+          return;
+        }
+      }
+      if (log->Length() ==
+            std::max(1u, StaticPrefs::browser_contentblocking_originlog_length())) {
+        // Cap the size at the maximum length adjustable by the pref
+        log->RemoveElementAt(0);
+      }
+      log->AppendElement(LogEntry{aType, 1u, aBlocked});
     } else {
       entry.OrInsert([=] {
         auto log(MakeUnique<OriginLog>());
-        log->AppendElement(mozilla::MakePair(aType, aBlocked));
+        log->AppendElement(LogEntry{aType, 1u, aBlocked});
         return log.release();
       });
     }
   }
 
   nsAutoString Stringify()
   {
     nsAutoString buffer;
@@ -71,18 +92,19 @@ public:
         w.EndArray();
         continue;
       }
 
       w.StartArrayProperty(NS_ConvertUTF16toUTF8(iter.Key()).get(), w.SingleLineStyle);
       for (auto& item: *iter.UserData()) {
         w.StartArrayElement(w.SingleLineStyle);
         {
-          w.IntElement(item.first());
-          w.BoolElement(item.second());
+          w.IntElement(item.mType);
+          w.BoolElement(item.mBlocked);
+          w.IntElement(item.mRepeatCount);
         }
         w.EndArray();
       }
       w.EndArray();
     }
 
     w.End();
 
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -1617,16 +1617,24 @@ VARCACHE_PREF(
 )
 
 VARCACHE_PREF(
   "browser.contentblocking.allowlist.annotations.enabled",
    browser_contentblocking_allowlist_annotations_enabled,
   bool, true
 )
 
+// How many recent block/unblock actions per origins we remember in the
+// Content Blocking log for each top-level window.
+VARCACHE_PREF(
+  "browser.contentblocking.originlog.length",
+   browser_contentblocking_originlog_length,
+  uint32_t, 32
+)
+
 // Whether FastBlock has been enabled.
 VARCACHE_PREF(
   "browser.fastblock.enabled",
   browser_fastblock_enabled,
   bool, false
 )
 
 // Anti-tracking permission expiration
--- a/uriloader/base/nsIWebProgressListener.idl
+++ b/uriloader/base/nsIWebProgressListener.idl
@@ -482,20 +482,22 @@ interface nsIWebProgressListener : nsISu
    *        A value composed of the Security State Flags and the Security
    *        Strength Flags listed above.  Any undefined bits are reserved for
    *        future use.  This represents the security state after the change.
    * @param aContentBlockingLog
    *        An optional JSON string representing a log of the content blocking
    *        events happened so far.  This will be a JSON object containing keys
    *        representing origins that content blocking has acted on, with values
    *        being an array of items, each representing one action.  Each action
-   *        itself is an an array containing two elements, the first element
+   *        itself is an an array containing three elements, the first element
    *        being a blocking code from one of the Security State Flags above, and
    *        the second element being a boolean representing whether the origin
-   *        was blocked (if true) or unblocked (if false) in that category.
+   *        was blocked (if true) or unblocked (if false) in that category, and
+   *        the third element being the number of times that combination has been
+   *        repeated consecutively.
    *
    * NOTE: These notifications will only occur if a security package is
    * installed.
    */
   void onSecurityChange(in nsIWebProgress aWebProgress,
                         in nsIRequest aRequest,
                         in unsigned long aOldState,
                         in unsigned long aState,