How to restore native browser object without creating iframe? - javascript

I make an embedded JS code which works on thousands of different sites. I definitely want to use some standard browser features (like window.JSON.stringify), but sometimes it simply doesn't work, because a site has some code that ran before mine and replaced native object with something incompatible with my expectations (and standards of course).
Unfortunately the way of restoring native functions by deleting them (delete JSON.stringify) doesn't work in this case because I need to restore a whole object, not only its method. I've heard about a handy way to restore native object, which is iframe creation for getting a new window instance:
function getNativeJSON() {
if (!window.JSON || !/native code/.test(window.JSON.stringify.toString()) {
var iframe = document.createElement('iframe');
document.documentElement.appendChild(iframe);
return iframe.contentWindow.JSON;
}
return window.JSON;
}
This approach works fine for me, but sometimes (very rarely, about 1 of 10000 executions) fails. I guess this can be a consequence of some weird behavior like iframe that isn't loaded yet or anything else. Thus this method is neither elegant enough (or I just don't like it), nor can be easily reproduced and debugged.
Maybe do you know any way to restore native browser objects, like JSON?
UPDATE: Of course the iframe I use is appended to DOM before.

Related

How can I clone a <browser> element in Firefox using XUL?

I am developing a firefox extension where I need to save the state of an arbitrary web page in order to be able to restore that webpage later. The quirk is that I need to restore the entire state of the page, including the state of all javascript variables. The "saving" can be done in memory, it doesn't need to be serializable.
So, is there a way to exactly clone a browser element, so that it starts running from the same point of execution that the original is currently at?
If not, how much effort would it require to add this to firefox (using C++), and which files and documentation would I start looking at?
No, there isn't a way to do exactly what you want. Even the built-in session restore will only restore form fields (and some other selected things), but not the full JS and native object state.
Implementing something like this yourself not feasible (and would be also a massive task):
You could uneval() most js objects, but that will loose type information and you'll only get the source, but not any internal state (think "hidden" state via closures). Native objects like window or document need some special treatment, and getting the internal state isn't exactly always possible here without some C++-level "reflection".
You could potentially get a lot of the actual state using the debugger API in new ways, however I don't see any way to actually restore it later. And "a lot" is still not the same as "all".
About the closed-over "hidden" state:
There is no way I know of to reliably get the internal state of counter in the following example, let alone restore it later, without getting as low-level as a platform-dependent full memory dump.
var count = (function() {
var counter = 0;
return function() { return ++counter; };
})();
count();
count();
I guess that you could walk the properties of all objects and save them somewhere but preserving context of e.g. bound functions would be difficult. Maybe you could make some use of the session store?
See:
Session_store_API and nsISessionStore

Count all objects and variables in use

Is it possible to count created objects and variables in javascript?
I am using Google Chrome to analyse my web app. But to debug and find the objects that causes "Memory Leak" is not so easy (at least for me). So I want to know all objects and variables that are created on the current page so I can know if they are removed.
No, you can't do that in Chrome (or any other major browser). You can use Chrome's "memory" page (chrome://memory/) to get some idea what's going on, but it's not down to the object level, and it's important to understand that garbage collection does not happen synchronously or immediately. The browser / JavaScript engine may well allocate memory, use it for some JavaScript objects, and then later correctly understand that those objects aren't used anymore, but keep the memory handy for future use.
Instead, what you can do is study how JavaScript works in detail, which tells you what will (usually) be kept in memory, and why. Understand how closures work (disclosure: that's a post on my anemic little blog), and understand how IE doesn't handle circular references between DOM elements and JavaScript objects well (specifically, it doesn't clean them up well when nothing refers to either of them anymore, which is otherwise not normally a problem). And in general, don't worry too much about it until/unless you have a specific issue to address. (Which absolutely happens, but not as much as people sometimes think.)

Is it possible to detect page modification through userscripts? [duplicate]

This question already has answers here:
Can a website know if I am running a userscript?
(2 answers)
Closed 9 years ago.
If you have a website, can you somehow find out if visitors are modifying your site with javascript userscripts?
In short: EEEEEEK! Don't do it! Rather, decide what needs to be guarded, and guard that. Avoid polling (periodical checking) at all costs. Especially, avoid periodical heavy checks of anything.
Not every change is possible to track. Most changes are just extremely hard to track, since there are so many things that could change.
Changes to the DOM (new nodes, removed nodes, changed attributes) can be detected. The other answer suggests checking innerHTML periodically, but it's better to use mutation observers (supported by Firefox, Chrome) or the older mutation events (DOMSubtreeModified et al.) (support varies by event) instead.
Changes to standard methods cannot be reliably detected, except by comparing every single method and property manually (eeeek). This includes the need to reference tons of objects including, say, Array.prototype.splice (and Array and Array.prototype as well, of course), and run a heavy script periodically. However, this is not what a userscript typically does.
The state of an input is a property, not an attribute. This means that the document HTML won't change. If the state is changed by a script, the change event won't fire either. Again, the only solution is to poll every single input manually (eeek).
There is no reliable way to detect if an event handler has been attached. For starters, you would need to guard the onX attributes (paragraph #2), detect any call to addEventListener (ek) (without tripping the paragraph #2 check), detect any calls to the respective methods by your library (jQuery.bind and several others).
One thing that plays in your favor, and possibly the only one: user scripts run on page load (never sooner), so you have plenty of time to prepare your defenses. not even that plays in your favor (thanks Brock Adams for noting and the link)
You can detect a standard method has been called by replacing it with your own (ek). There are many methods that you would need to instrument this way (eek), some by the browser, some by your framework. The fact that IE (and even firefox can be instructed to, thanks #Brock) won't let you touch the prototypes of the DOM classes adds another "e" or two to the "eek". The fact that some methods can only be obtained via a method call (return value, callback arguments) adds another "e" or two, for a total of "eeeek". The idea of crawling across the entirety of window will be foiled by security exceptions and uncatchable security exceptions. That is, unless you don't use iFrames and you are not within an iFrame.
Even if you detect every method call, DOM can be changed by writing to innerHTML. Firefox and Chrome support Mutation Observers, so you can use these.
Even if you detect every method call to a pre-existing method and listen to mutations, most properties are reflected by neither, so you need to watch all properties of every object as well. Pray someone does not add a non-enumerable property with a key you would never guess. Incidentally, this will catch DOM mutations as well. In ES6, it will be possible to observe an object's property set. I'm not sure if you can attach a setter to an existing object property in ES5 (while adhering to ES3 syntax). Polling every property is eeeek.
Of course, you should allow your own scripts to do some changes. The work flow would be to set a flag (not accessible from the global scope!) "I'm legit", do your job, and clear the flag - remember to flank all your callbacks as well. The method observers will then check the flag is set. The property watchdogs will have a harder time detecting if a change is valid, but they could be notified from the script of every legit change (manually; again make sure the userscripts cannot see that notification stream). Eeek.
There's an entirely different problem that I didn't realise at first: Userscripts run at page load, but they can create an iFrame as well. It's not entirely inconcievable (but still unlikely now) that a userscript would: 1) detect your script blocker, 2) nuke the page from the orbit (you can't prevent document.body.innerHTML =, at least not without heavily tampering with document.body), 3) insert a single iframe with the original URL (prevent double loads server-side?) and 4) have a plenty of time to act on that empty iframe before your protection is even loaded.
Also, see the duplicate found by Brock Adams, which shows several other checks that I didn't think of that should be done.
If you don't have script yourself that changes things you cold compare document.body.innerHTML and document.head.innerHTL with what it was.
When you do change DOM in your script you can update the values to compare it with. Use setInterval to compare periodically.

How to "correctly" create an object which inherits from Element?

I am writing an HTML5 application that involves a lot of XML manipulation, part of this manipulation involves comparing the versions of two different XML Elements.
What I need is for every Element, Attr, and TextNode (all of which inherit from Node, AFAIK) object that gets created to have associated version information, but still be able to behave like a normal Element, Attr, or TextNode. The current working solution I am using to store the version information, is the following:
Node.prototype.MyAppAnnotation = {
Version : null
};
Now, I understand that augmenting built-in types is considered bad form, but beyond this technique, I'm at a loss for how to get the desired functionality. I don't think I can encapsulate the Node in a wrapper because I need the Node related properties and functions exposed on the wrapper. I might be able to write some sort of pass-through functions for the wrapper, but that seems really clunky.
I feel that because the app I'm writing is an HTML5 app, and as such only has to run on the most modern browsers (all of which support the augmentation of built-ins), makes this technique appropriate. Also, by providing a sufficiently obscure name to my augmentation object, I can avoid all naming collisions (except for intentional collisions). I've also explored inheritance-based solution using Google's Closure library. However, it appears that because Element, Node and TextNode don't have direct constructors (i.e. they're created off of a Document object), this technique will not work either.
I was wondering if someone could either a) recommend an elegant way of achieving this effect without augmenting Element, or b) provide a compelling reason for why I shouldn't break the "don't augment built-ins" rule in this case.
Many Thanks,
Jarabek
Your idea is theoretically valid, but there's a weird feeling I get when reading about it.
First of all - you don't have to augment any prototypes. If you just do somedomnode.myweirdname='foo' it will become a field of that object. That's what javascript does ;)
So when there is no version you'll get undefined instead of null.
But, if you want to add more functionality or wrap dom node in anything - there's a bit of history of doing that. Most of that history is dominated by stuff like jQuery :)
Just create an object that has a field containing the node. And then you can access it really simply:
myobject.node
And create the object with some constructor or just factory function:
var myobject = createDomNodeWrapper(domnode)

intercepting javascript alert()..? is it acceptable?

I just found we can intercept the javascript alert() native call and hook the user code before the actual execution. check out the sample code..
function Test(){
var alertHook=function(aa){
this.alert(aa);
}
this.alert("aa");
this.alert = alertHook;
alert("aa");
}
so everytime i call alert("aa") is been intercepted by my alertHook local function. But the below implementation with the small change does not work.
function Test(){
var alertHook=function(aa){
alert(aa);
}
alert("aa");
alert = alertHook; //throws Microsoft JScript runtime error: Object doesn't support this action
alert("aa");
}
it throws Microsoft JScript runtime error: Object doesn't support this action.
I dont know how this.alert = alertHook; let me intercept the call, but alert=alertHook; not.??
So i assume using this to intercept any native js methods.? is that right?
And is that acceptable? because this way i can completely replacing any native JS calls with my own methods??
UPDATE:
I asked is that acceptable? because how this is a good approach having eval() and letting users to replace native function calls?
And its responsibility of a language to protect developers from the misleading features, replacing the native js calls in a window level(or in a common framework js file) would crash the whole system.. isn't it??
i may be wrong in my opinion because i dont understand the reason behind this feature..? I never seen a language that let developer to replace its own implementation..
Depending on how Test(); is being called, this should be the window Object.
I believe Microsoft allows overwriting native JS functions only by specifying the window object.
So window.alert = alertHook; should work anywhere.
is it acceptable?
Yes it is. This is a major strength for the flexibility of the language, although I'm sure there's better alternatives instead of overwriting native behavior.
Overwriting native JavaScript functions isn't really a security issue. It could be one if you're running someone elses code that does it; but if you're running someone elses code there's a lot of other security issues you should be concerned about.
In my opinion, it never is good practice to redefine the native functions. It's rather better to use wrappers (for instance, create a debug function that directs its output to alert or console.log or ignores the calls or whatever suits your needs).
As for why JScript throws an exception with your second example and not the first one, it's easy. In the first example, you create a property called alert in your local scope, so when you refer alert you'll be referring this.alert rather than window.alert. In the second example, the alert you're referencing is the one from window, so assigning a different function to it will fail.
And its responsibility of a language to protect developers from the misleading features, replacing the native js calls in a window level(or in a common framework js file) would crash the whole system.. isn't it??
Not true, replacing the native call only hooks into it, replaces it: it does not rewrite the native at all. Crashing the "whole" system; JavaScript runs in a Virtual Machine, it's interpreted, so the chance of crashing the "whole" system (i.e. Blue Screen of Death?) is very very small. If so: it's not the programmers fault, but the implementation of JavaScript which is causing the error.
You can consider it as a feature: for instance, if you load a JavaScript from someone else's hand, you can reimplement some functions to extend.
Protection to the programmer is like keeping a dog on the leash: only unleash it, when you trust the dog! Since JavaScript runs in a Virtual Machine, any programmer can be unleashed -- if the implementation is secure enough, which it is (most of the time?)

Categories

Resources