4

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 : )

Dev Doomari
  • 943
  • 10
  • 19
  • `__defineGetter__` and `__defineSetter__` are non-standard and not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. – rafaelcastrocouto Mar 10 '14 at 14:43
  • Just to say, several of the answers here don't seem to be understanding the question. – Scimonster Mar 10 '14 at 14:43
  • Regardless of what security measures you put in place you can still never trust external code. It's still only a matter of a simple edit to nullify your setter/getter logic. – Etheryte Mar 10 '14 at 14:48

3 Answers3

5

__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.

Scimonster
  • 32,893
  • 9
  • 77
  • 89
  • this works for elements created with `document.createElement` after defining the property – rafaelcastrocouto Mar 10 '14 at 14:45
  • 1
    I tried a lot of experiments... but it seems that JS just can't do what I want it to do... but this answer is closest to what I wanted to do (something like pre-processing in JS?) - so I'll accept yours : ) – Dev Doomari Mar 12 '14 at 07:22
  • On most browser u don't need to delete the attribute from the object, it just works on the prototype-level. On Chrome u'd need to `delete object.src` in order for this trick to work. Thanks. – HLL May 28 '14 at 15:27
2

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/

dfsq
  • 191,768
  • 25
  • 236
  • 258
  • I think yours are also somewhat close, but it only works when "var target = document.querySelector('#image');" is loaded AFTER the DOM element...but anyway, here's your +1 since it's close anyway : ) – Dev Doomari Mar 12 '14 at 07:22
0
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');
    }    
}
alexP
  • 3,672
  • 7
  • 27
  • 36