/* 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/. */
/* globals browser exportFunction Sanitizer */
"use strict";
const SMARTBLOCK_EMBED_OBSERVER_TIMEOUT_MS = 10000;
/**
* Helper library to create shims for Smartblock Embeds
*
*/
const embedHelperLib = (() => {
let prevRanShims = new Set();
let originalEmbedContainers = [];
let embedPlaceholders = [];
let modifiedContainers = [];
let observerTimeout;
let newEmbedObserver;
function sendMessageToAddon(message, shimId) {
return browser.runtime.sendMessage({ message, shimId });
}
function addonMessageHandler(message, SHIM_INFO) {
const { topic, shimId: sendingShimId } = message;
const { shimId: handlingShimId, scriptURL } = SHIM_INFO;
// Only react to messages which are targeting this shim.
if (sendingShimId != handlingShimId) {
return;
}
if (topic === "smartblock:unblock-embed") {
if (newEmbedObserver) {
newEmbedObserver.disconnect();
newEmbedObserver = null;
}
if (observerTimeout) {
clearTimeout(observerTimeout);
observerTimeout = null;
}
// Remove placeholder and restore original containers
embedPlaceholders.forEach((placeholder, idx) => {
const modifiedContainer = modifiedContainers[idx];
const originalContainer = originalEmbedContainers[idx];
// Replace the modified container with the original
modifiedContainer.replaceWith(originalContainer);
});
// Clear the arrays
embedPlaceholders = [];
modifiedContainers = [];
originalEmbedContainers = [];
// recreate scripts
let scriptElement = document.createElement("script");
// Set the script element's src with the website's principal instead of
// the content script principal to ensure the tracker script is not loaded
// via the content script's expanded principal.
scriptElement.wrappedJSObject.src = scriptURL;
document.body.appendChild(scriptElement);
}
}
/**
* Replaces embeds with a SmartBlock Embed placeholder. Optionally takes a list
* of embeds to replace, otherwise will search for all embeds on the page.
*
* @param {HTMLElement[]} embedContainers - Array of elements to replace with placeholders.
* If the array is empty, this function will search
* for and replace all embeds on the page.
*
* @param {object} SHIM_INFO - Information about the shim wrapped in an object.
*/
async function createShimPlaceholders(embedContainers, SHIM_INFO) {
const { shimId, embedSelector, embedLogoURL, isTestShim } = SHIM_INFO;
// Check if we should show embed content in placeholders.
// This requires the Sanitizer API (setHTML), available in Firefox 148+.
const shouldShowEmbedContent = await sendMessageToAddon(
"shouldShowEmbedContentInPlaceholders",
shimId
);
const [titleString, descriptionString, buttonString] =
await sendMessageToAddon("smartblockGetFluentString", shimId);
if (!embedContainers.length) {
// No containers were passed in, do own search for containers
embedContainers = document.querySelectorAll(embedSelector);
}
embedContainers.forEach(originalContainer => {
// this string has to be defined within this function to avoid linting errors
// see: https://github.com/mozilla/eslint-plugin-no-unsanitized/issues/259
const SMARTBLOCK_PLACEHOLDER_HTML_STRING = `