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

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

Related

Detecting if there is a change in a localStorage variable

I have a case where I need to pass a variable from a modal back to the main screen. I have decided the cleanest way to do so is to store that value in localStorage so that I can pass it back to the main file and then display it on the main page.
Is there a way to listen to the localStorage item being changed? I've been searching, but only have found information getting and setting the variable.
My item looks like this.
var length = $('.table').find('tbody').find('tr').length;
localStorage.setItem('length', length);
There's a storage event on window object for local storage changes.
MDN local storage api
So you can watch the changes. But, if I am correct, that would work only for the same domain frames. So if they are, this is your choice.
you can use a global scope like define it out of function and it will be one global scope.
var globalVariable={
x: 'globalval'
};
or use...
window.globalvar1='test' //it will set to global.
that way it will be bind to window scope.
when you set the item, always first do a get and compare with that value,
if value is changed notify, otherwise set.
var length = $('.table').find('tbody').find('tr').length;
if(localStorage.getItem(length)){
localStorage.getItem(length)!=length?notifyChange():
}
Note: This is an expensive and overly complicated approach but meets your needs for pure localStorage.
If you must use localStorage the only way I can think of that you can watch/listen for a variable in localStorage is like so
setInterval(function(){
var modalValue = localStorage.getItem( 'length' );
if( modalValue ){
// use the value
// remove the value when you are done so that this code doesn't run every time
localStorage.setItem( 'length', null );
}
}, 100 );
This will check for the variable every 1/10 of a second and run the code when it's set.
You mentioned in a comment that it is complicated and that their are iframes involved. Perhaps you can leverage the messaging api to better meet your needs?
Don't use localstorage for critical functionality. localstorage is blocked completely when using private browsing on certain browsers.
Only use localstorage for non-critical enhancements.
There is no callback for localstorage, so you wont be able to monitor changes as they happen. You could however pull the value on page load, store the value in your execution context and watch for that value to change.
Otherwise, to do what you want will require using a database.
Don't do this, find a mechanism of dependency injection that will let you pass the the variable in a sane manner. Do that either with something akin to Angular.js' service/factory pattern, or a React store.
Leveraging a mechanism like that will also allow you to listen for changes to whatever you're storing. In fact, that's the whole point of things like RxJS Observables which are at the core of Angular2+'s framework.
Additionally, something like couchdb would let you persist this data asynchronously and still not have the drawbacks of coordinating globals through raw localstorage.
Allowing for uncontrolled access to some global variable is just asking for a defect.

JavaScript clean memory

I have a problem about memory management.
My simpliest code is here:
var url="/abrapo.php";
var ob={start_:100, token:null}
function post_token(){
$.post(url,{access:ob.token})
.done(function(data){
console.log(data);
ob=data;
});
}
I call function post_token every seconds. So after 2000 call user has problem of memory, ram goes up to 2GB. I don't need to save anything just want to log data after post and clear memory. I've already googled and find delete ob. But it does not clean the memory. What increase memory and how can I clean it without reloading the page
Use your browser's profiling tools to determine where you're accumulating memory. In Chrome these profiling tools are located under the Performance tab in the Chrome Developer Tools F12.
Click the Memory checkbox near the top to enable memory profiling
Click Start Profiling and Reload Page (Ctrl+Shift+E)
Let the profiling run for a while, most pages load in 2-3 seconds but it sounds like your page needs to run longer than that
Click the Stop button to halt the profiling
Among all the other performance graphs, you should see one for memory usage that looks something like this.
You can use this to see if, and when, the browser is performing garbage collections on the Javascript heap. You may need to manually clear certain objects by setting them to null. Also, try to avoid cyclical references and other complex referencing patterns that could cause the javascript engine to hold on to objects longer than it has to.
Click here, for more about the memory management and garbage collection in the browser.
I had similar problems while writing UI for a data acquisition device and managed to make it fly by setting every variable containing large data arrays to null whenever not used.
Your use case isn't easy to replicate with just your code, but I suggest you try setting
data = null;
and
ob = null;
whenever not in use.
You might have to tweak suggestion a bit, say by assigning only token:
ob.token = data.token;
in such case only token would have to be set to null
ob.token = null;
What this achieves essentially is that it gives garbage collector a chance to clear unused objects since variables using those were clearly set to null. Oh, yes, and memory profiling is your friend to find out what exactly should you null
According to your code example, the problem is with console.log(data)
it make your object accessible from Console. The Garbage collection will free memory only when the object is no more accessible.

How to know if element created with document.createElement still exists

I'm creating an anchor element using document.createElement in my PhantomJS tests like this:
var mockLink = null;
beforeEach(function() {
mockLink = document.createElement('a');
});
it('should foo', function() {
// Use mockLink in some way
});
I want to clean up the element in the afterEach code so that each test will have a newly-created instance of it. Unfortunately, element.remove() isn't supported in PhantomJS. Source
afterEach(function() {
mockLink.remove(); // Error!
});
And I want to do this without adding the webpage plugin.
removeChild is supported by PhantomJS, but my newly-created element doesn't have a parent:
mockLink.parentElement // undefined
mockLink.parentElement.removeChild(mockLink); // doesn't work
mockLink.parentNode // also undefined
My newly-created link also doesn't seem to be on the document at all.
mockLink.href = 'www.google.com';
document.getElementsByTagName('a'); // doesn't contain google.com
So I can't do
document.removeChild(mockLink);
mockLink.ownerDocument.contains(mockLink) also returns false
It seems like there are no references to mockLink stored anywhere besides my mockLink variable, meaning that I can just set mockLink equal to null if I want to let that memory be freed up by garbage collection. But how do I verify this works? If I set any other variable to mockLink and then console.log it, it will still come out as defined since it will be a new reference to the same space in memory. How do I verify that mockLink is really being deleted when I set the variable to null?
You've found yourself a conundrum.
If you kill all references to the element by setting mockLink = null and making sure there are no other references to the element, then the garbage collector should be able to free that object.
But, you cannot verify that because in order to verify that the element is no longer available, you'd have to keep a reference to it, but that would prevent it from getting garbage collected in the first place. Thus, the conundrum.
This is an issue that can't really be measured directly from Javascript itself.
If you want to design a one-time test to make sure the memory is being reclaimed, then you can take a memory snapshot, create a several hundred thousand objects stored in an array, clear the array, wait a short time for GC to run, take another memory snapshot, repeat the same process several more times and verify that memory usage of the process is not steadily increasing or study the memory snapshot to make sure none of those objects appear in the memory footprint.
If your javascript environment supports weak references then you can create a weak reference to the node. Depending on the implementation notification mechanisms such as callbacks or reference queues that tell you when it has been collected may also be available.
Unprivileged javascript contexts in web browsers currently don't offer such an API. Node.js, Nashorn and browser addon environments do.

Can variables in JS function closures be accessed in any way (including devtools)? How?

In my previous question:
Securing javascript game timing
... it became clear that client-side timing in a Javascript/Canvas game simply won't be secure. I know the mantra about not trusting the client - that is what is causing my struggle in the first place. :-)
So, if I do move all timing to the server and just deal with it, here is a follow-up question. The game obviously needs to be completed before submitting it. As the game puzzle is all Javascript, this introduces the problem of manipulating the client-side code to fake the completion of the game.
I've created the game JS code in a separate class file. If I instantiate the game as such:
var game;
$document.ready(function(){
game = new Game();
});
... then, I can access the 'game' object and all of its methods and variables via the console.
However, if I do:
$document.ready(function(){
var game = new Game();
});
... then I cannot access the 'game' object through the console. This seems to help, but is there something I don't know - can this object still be accessed in some way I don't know about or is making it a private var in that function a little more secure?
Thanks!
Note: there are many other security considerations and attack vectors in such a system. This answer just seeks to answer the specific question that was asked here.
It depends on the browser and what its devtools provide. Most browsers' devtools provide functionality to:
pause execution of JavaScript at any point in time and use a debugger interface.
variables that are in-scope at the current point of execution where the debugger is paused can usually be accessed via devtools in various ways. Inparticular, via console, where anything one can do with that variable in the console is fair game: query its fields, call its methods, etc. If the variable binding isn't const, one can even reassign the variable to a new user-created instance of the object.
navigate JS files and set breakpoints in them.
this is a vector to the above bullet point.
you can make this less attractive by using JS minification (ie. obfuscation), but that's not going to stop someone who's determined.
String literals don't get minified and can usually help a lot in navigating and understanding minified code.
inspect event listeners on HTML elements and set breakpoints on them.
If a variable has a reference bound to it in a function closure that is known to be an event listener of a certain HTML element, or reachable (execution-wise) by such an event listener, this can be another vector to the first bullet point. This can be very common in web games. Just a keyboard event listener usually is an entry-point to reach functions that reference important game objects.
There are even tools to record the JS heap memory. It's a lot of data to sift through, but it's basically everything on the JS heap (readonly).
Given those browser features (and the fact that a user can use any browser they wish), it's impossible to "safeguard" anything 100% on the client-side. It's a losing battle. If you want to play it like a game, you can do your best.
Look into Object.freeze and friends.
freeze or seal anything that can be frozen or sealed, including class prototypes
make variables which can be const const
use assertions to assert in critical parts of the logic that the program state is consistent and try to detect tampering.
Don't care too much about the console. Yes, if there are global objects whose method can easily be fired to "win" the game, it's a nice possibility to cheat, but it can easily prevented as you demonstrated.
So, the hacker would just listen (look at the network pane) which requests are made to your server and fire them manually. If they were just some simple urls like /action=start and /action=end, he could very easily fire them manually without any timing. So you will need to prevent that (although you never can really make it safe), e.g. by adding additional credential tokens. Or you could embed some "secret"(s) into the game code, which are revealed during the gameplay, and need to be sent to the server to prove the rightfulness. Of course they could be read out of your code, but you have to make it too complicated for the hacker. It's a bit like security by obscurity…

Why is it faster to access the DOM through a cached variable?

I am trying to improve my knowledge of javascript and while searching for some "best practices", someone pointed out to me that it is faster to cache the DOM document and then access it through that var instead of accessing the document object directly.
You can see the results here, on an edit I made on jsperf: http://jsperf.com/jquery-document-cached-vs-uncached/3 (edit: the title holds "jsquery" because that was the original test, my edit contains vanilla javascript, the framework makes no difference)
This really makes me curious. Basically I am introducing a new variable into the equation, how can that make things faster instead of slower?
As far as I know, "print a" should be better than "b = a; print b" (figure of speach)
What's different in this case?
document is not like an ordinary Javascript variable. There's no telling what odd magic is happening under the covers when accessing its attributes, especially the DOM, which may be created on demand from internal browser structures.
I believe I found an explanation here (the emphasis on the last part is mine):
Store pointer references to in-browser objects. Use this technique to
reduce DOM traversal trips by storing references to browser objects
during instantiation for later usage. For example, if you are not
expecting your DOM to change you should store a reference to DOM or
jQuery objects you are going to use when your page is created; if you
are building a DOM structure such as a dialog window, make sure you
store a few handy reference to DOM objects inside it during
instantiation, so you dont need to find the same DOM object over an
over again when a user clicks on something or drags the dialog
window.If you haven’t stored a reference to a DOM object, and you need
to iterate inside a function, you can create a local variable
containing a reference to that DOM object, this will considerably
speed up the iteration as the local variable is stored in the most
accessible part of the stack.
So, if I understand correctly, caching the DOM in a local variable makes it easier to access in the memory stack, therefore increasing the speed of execution.

Categories

Resources