Index: include.preload.js
===================================================================
--- a/include.preload.js
+++ b/include.preload.js
@@ -15,31 +15,40 @@
  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 "use strict";
 
 let {splitSelector} = require("common");
 let {ElemHideEmulation} = require("content_elemHideEmulation");
 
+const {hash} = require("hash");
+
 // This variable is also used by our other content scripts.
 let elemhide;
 
 const typeMap = new Map([
   ["img", "IMAGE"],
   ["input", "IMAGE"],
   ["picture", "IMAGE"],
   ["audio", "MEDIA"],
   ["video", "MEDIA"],
   ["frame", "SUBDOCUMENT"],
   ["iframe", "SUBDOCUMENT"],
   ["object", "OBJECT"],
   ["embed", "OBJECT"]
 ]);
 
+function hashSelectors(selectors)
+{
+  if (!selectors || selectors.length == 0)
+    return 0;
+  return hash(new TextEncoder("utf-8").encode(selectors.join()));
+}
+
 function getURLsFromObjectElement(element)
 {
   let url = element.getAttribute("data");
   if (url)
     return [url];
 
   for (let child of element.children)
   {
@@ -342,25 +351,35 @@
 function ElemHide()
 {
   this.shadow = this.createShadowTree();
   this.styles = new Map();
   this.tracer = null;
   this.inline = true;
   this.inlineEmulated = true;
   this.emulatedPatterns = null;
+  this.digests = new Map();
 
   this.elemHideEmulation = new ElemHideEmulation(
     this.addSelectors.bind(this),
     this.hideElements.bind(this)
   );
 }
 ElemHide.prototype = {
   selectorGroupSize: 1024,
 
+  selectorsChanged(selectors, groupName)
+  {
+    let digest = hashSelectors(selectors);
+    if (digest == this.digests.get(groupName))
+      return false;
+    this.digests.set(groupName, digest);
+    return true;
+  },
+
   createShadowTree()
   {
     // Use Shadow DOM if available as to not mess with with web pages that
     // rely on the order of their own <style> tags (#309). However, creating
     // a shadow root breaks running CSS transitions. So we have to create
     // the shadow root before transistions might start (#452).
     if (!("createShadowRoot" in document.documentElement))
       return null;
@@ -449,16 +468,19 @@
       ).join(", ");
       style.sheet.insertRule(selector + "{display: none !important;}",
                              style.sheet.cssRules.length);
     }
   },
 
   addSelectors(selectors, filters)
   {
+    if (!this.selectorsChanged(selectors, "emulated"))
+      return;
+
     if (this.inline || this.inlineEmulated)
     {
       // Insert the style rules inline if we have been instructed by the
       // background page to do so. This is usually the case, except on platforms
       // that do support user stylesheets via the browser.tabs.insertCSS API
       // (Firefox 53 onwards for now and possibly Chrome in the near future).
       // Once all supported platforms have implemented this API, we can remove
       // the code below. See issue #5090.
