Index: lib/content/snippets.js
===================================================================
--- a/lib/content/snippets.js
+++ b/lib/content/snippets.js
@@ -10,18 +10,67 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+/* eslint-env webextensions */
 /* eslint no-console: "off" */
 
 "use strict";
 
+function injectCode(code)
+{
+  let script = document.createElement("script");
+
+  script.type = "application/javascript";
+  script.async = false;
+
+  // Firefox 58 only bypasses site CSPs when assigning to 'src',
+  // while Chrome 67 only bypasses site CSPs when using 'textContent'.
+  if (browser.runtime.getURL("").startsWith("chrome-extension://"))
+  {
+    script.textContent = code;
+    document.documentElement.appendChild(script);
+  }
+  else
+  {
+    let url = URL.createObjectURL(new Blob([code]));
+    script.src = url;
+    document.documentElement.appendChild(script);
+    URL.revokeObjectURL(url);
+  }
+
+  document.documentElement.removeChild(script);
+}
+
+function stringifyFunctionCall(func, ...params)
+{
+  return `"use strict";(${func})(${params.map(JSON.stringify).join(",")});`;
+}
+
+function makeInjector(injectable)
+{
+  return (...args) => injectCode(stringifyFunctionCall(injectable, ...args));
+}
+
 function log(...args)
 {
   console.log(...args);
 }
 
 exports.log = log;
+
+// This is an implementation of the uabinject-defuser technique used by uBlock
+// Origin
+// https://github.com/uBlockOrigin/uAssets/blob/c091f861b63cd2254b8e9e4628f6bdcd89d43caa/filters/resources.txt#L640
+function uabinjectDefuser()
+{
+  window.trckd = true;
+  window.uabpdl = true;
+  window.uabInject = true;
+  window.uabDetect = true;
+}
+
+exports["uabinject-defuser"] = makeInjector(uabinjectDefuser);
