summaryrefslogtreecommitdiff
path: root/data/extensions/uBlock0@raymondhill.net/js/resources/create-html.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/uBlock0@raymondhill.net/js/resources/create-html.js')
-rw-r--r--data/extensions/uBlock0@raymondhill.net/js/resources/create-html.js113
1 files changed, 113 insertions, 0 deletions
diff --git a/data/extensions/uBlock0@raymondhill.net/js/resources/create-html.js b/data/extensions/uBlock0@raymondhill.net/js/resources/create-html.js
new file mode 100644
index 0000000..c5732d3
--- /dev/null
+++ b/data/extensions/uBlock0@raymondhill.net/js/resources/create-html.js
@@ -0,0 +1,113 @@
+/*******************************************************************************
+
+ uBlock Origin - a comprehensive, efficient content blocker
+ Copyright (C) 2025-present Raymond Hill
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ 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 this program. If not, see {http://www.gnu.org/licenses/}.
+
+ Home: https://github.com/gorhill/uBlock
+
+*/
+
+import { registerScriptlet } from './base.js';
+import { safeSelf } from './safe-self.js';
+
+/******************************************************************************/
+
+/**
+ * @scriptlet trusted-create-html
+ *
+ * @description
+ * Element(s) from a parsed HTML string are added as child element(s) to a
+ * specific parent element in the DOM.
+ *
+ * @param parent
+ * A CSS selector identifying the element to which created element(s) will be
+ * added.
+ *
+ * @param html
+ * An HTML string to be parsed using DOMParser, and which resulting elements
+ * are to be added as child element(s).
+ *
+ * @param duration
+ * Optional. If specified, the time in ms after which the added elements will
+ * be removed. No removal will occur if not specified.
+ *
+ * */
+
+function trustedCreateHTML(
+ parentSelector,
+ htmlStr = '',
+ durationStr = ''
+) {
+ if ( parentSelector === '' ) { return; }
+ if ( htmlStr === '' ) { return; }
+ const safe = safeSelf();
+ const logPrefix = safe.makeLogPrefix('trusted-create-html', parentSelector, htmlStr, durationStr);
+ // We do not want to recursively create elements
+ self.trustedCreateHTML = true;
+ let ancestor = self.frameElement;
+ while ( ancestor !== null ) {
+ const doc = ancestor.ownerDocument;
+ if ( doc === null ) { break; }
+ const win = doc.defaultView;
+ if ( win === null ) { break; }
+ if ( win.trustedCreateHTML ) { return; }
+ ancestor = ancestor.frameElement;
+ }
+ const duration = parseInt(durationStr, 10);
+ const domParser = new DOMParser();
+ const externalDoc = domParser.parseFromString(htmlStr, 'text/html');
+ const docFragment = new DocumentFragment();
+ const toRemove = [];
+ while ( externalDoc.body.firstChild !== null ) {
+ const imported = document.adoptNode(externalDoc.body.firstChild);
+ docFragment.appendChild(imported);
+ if ( isNaN(duration) ) { continue; }
+ toRemove.push(imported);
+ }
+ if ( docFragment.firstChild === null ) { return; }
+ const remove = ( ) => {
+ for ( const node of toRemove ) {
+ if ( node.parentNode === null ) { continue; }
+ node.parentNode.removeChild(node);
+ }
+ safe.uboLog(logPrefix, 'Node(s) removed');
+ };
+ const append = ( ) => {
+ const parent = document.querySelector(parentSelector);
+ if ( parent === null ) { return false; }
+ parent.append(docFragment);
+ safe.uboLog(logPrefix, 'Node(s) appended');
+ if ( toRemove.length === 0 ) { return true; }
+ setTimeout(remove, duration);
+ return true;
+ };
+ if ( append() ) { return; }
+ const observer = new MutationObserver(( ) => {
+ if ( append() === false ) { return; }
+ observer.disconnect();
+ });
+ observer.observe(document, { childList: true, subtree: true });
+}
+registerScriptlet(trustedCreateHTML, {
+ name: 'trusted-create-html.js',
+ requiresTrust: true,
+ dependencies: [
+ safeSelf,
+ ],
+ world: 'ISOLATED',
+});
+
+/******************************************************************************/