Lusi
Lusi

Reputation: 39

MutationObserver Wrapper

Overview

This MutationObserver Wrapper should be able to provide developers with any changes that have been made in the DOM for security reasons.

Problem

I need a simple way to create a wrapper for MutationObserver. I just want to be informed when a MutationObserver was created on the page. Then I want to make sure the code runs before all other codes so that I can put it in an extension.

Code

This is what I tried:


const dump = console.log.bind(console);



    class Observer
    {
        static started = false
        static jacked = {}


        static start()
        {
            Observer.started = true;

            Observer.hijack( MutationObserver,  function constructor()
            {
                alert("CAREFUL!! - MutationObserver is running here!");

                return (Observer.jacked.MutationObserver).constructor.apply(this, [...arguments]);
            });

            // if (!Observer.fixes[document.domain])
            // {
            //     dump("not listining on: "+document.domain);
            //     return;
            // };
            //
            // Observer.fixes[document.domain]()
        }



        static hijack(target, impose)
        {
            let waiting = setInterval(()=>
            {
                if ((typeof target.prototype) !== "object"){ return };
                if ((typeof target.prototype.constructor) !== "function"){ return };

                clearInterval(waiting);
                let name = target.prototype.constructor.name;
                dump("hijacking: "+name);
                Observer.jacked[name] = target;
                Object.defineProperty(target.prototype, "constructor", {writable:false, configurable:false, enumerable:false, value:impose});
            },0);
        }





    let waiting = setInterval(() =>
    {
        let exists = ((typeof MutationObserver) !== "undefined");

        if ( !exists )
        {
            console.log("observer waiting for `MutationObserver`");
            return
        };

        if ( Observer.started )
        {
            clearInterval(waiting);
            console.log("observer already started .. exiting");
            return
        };

        clearInterval(waiting);
        Observer.start();
    }, 0);


Upvotes: 0

Views: 187

Answers (1)

argon
argon

Reputation: 449

Try something like this, however, be aware of what globalThis refers to in your extension:

    const jacked = {};

    jacked.MutationObserver = globalThis.MutationObserver;

    delete globalThis.MutationObserver;

    globalThis.MutationObserver = (class MutationObserver 
    {
        constructor()
        {
            console.log("jacked");
        }

        observe()
        {
            console.log("busy");
        }
    });

after running the above, anywhere, like in a function, you can test if your wrapper-test works like this:

    let watcher = (new MutationObserver(function(){}));
    watcher.observe();

You can use jacked to resume normal operation inside your supplementary class constructor by returning a new jacked.MutationObserver.

Upvotes: 1

Related Questions