Dev Doomari
Dev Doomari

Reputation: 997

getter/setter for src attribute in js?

Are there any way I can set getters and setters of src attribute of all HTMLSourceElements? I'm thinking about using this as an extra security measures for my web app which uses JS from other websites. By "setters of src attribute of all HTMLSourceElements", I mean that the setter should be called on code like: SomeVideoElement.src = "/static/somevideo.mp4"

So far, I've tried:

HTMLElement.prototype.__defineGetter__("src", function () {
    console.log("getter called!");
    debugger;
});
HTMLElement.prototype.__defineSetter__("src", function (val) {

    debugger;
});
//tested at chrome, didn't yield any logs (getters and setters not called)

and

HTMLSourceElement.prototype._setAttribute = HTMLSourceElement.prototype.setAttribute;
HTMLSourceElement.prototype._getAttribute = HTMLSourceElement.prototype.getAttribute;
HTMLSourceElement.prototype.setAttribute = function(){
   console.log("HTMLSourceElement.setAttribute called!");
   debugger;
   HTMLSourceElement.prototype._setAttribute.apply(this, arguments);
}
//tested at chrome. Called only for codes like: SomeVidElem.setAttribute("src",someurl)

are there any way to do this? Or is this simply impossible? Thanks : )

Upvotes: 4

Views: 2531

Answers (3)

dfsq
dfsq

Reputation: 193301

You should play with MutationObserver. For example this is how you can watch image properties changes:

var target = document.querySelector('#image');

var observer = new MutationObserver(function (mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation);
        alert('Change: ' + mutation.attributeName + ', ' + mutation.oldValue);
    });
});

observer.observe(target, {
    attributes: true,
    attributeOldValue: true
});

Support: all modern browsers and IE11+.

Demo: http://jsfiddle.net/dfsq/PmTHj/1/

Upvotes: 2

Scimonster
Scimonster

Reputation: 33409

__defineGetter__ and __defineSetter__ are deprecated and possibly obsolete. Object.defineProperty(parentObject, 'propName', {}) is the new way.

I couldn't get it to work, but maybe someone else can?

Object.defineProperty(HTMLSourceElement.prototype, 'src', {
    enumerable: true,
    configurable: true,
    get: function(){
        return this.getAttribute('src')
    },
    set: function(newval){
        console.log('being set');
        this.setAttribute('src',newval);
    }
});

EDIT: After a bit of experimentation, this should work if you then delete the src property of every element that you need to. A bit hacky, but the best i could do.

EDIT2: With this, a user could still theoretically overwrite your get/set functions. To stop that, try removing configurable: true (it will default to false). I'm not sure, but from past experience, it seems like they can't even redefine it on an instance.

Upvotes: 5

alexP
alexP

Reputation: 3765

var srcElements = document.querySelectorAll('[src]');
for(var i = 0; i < srcElements.length; i++){
    if( typeof(srcElements[i].src) != 'undefined' ){
        console.log(srcElements[i] + ' has a src property');
    }    
}

Upvotes: 0

Related Questions