Can the default `window.top` ever be invalid as a reference? - javascript

I want to redirect the user to an external page and simultaneously break out of a frameset.
The outermost frameset is most likely within the same domain as the page doing the redirection, but there is the possibility that it will span domains. In development, the outermost frameset might not even exist at all. Ideally, I want to cover all those situations.
The innermost page (the one that has the breakout code) is going to be served over HTTPS. The target URL may be HTTP or HTTPS. It is acceptable for the redirection to fail (there is a fallback link "click here to continue" to cover for that scenario) but the redirection should work in the majority of cases. Particularly for the purposes of this question, I'd hate for it to be more browser-dependent than necessary.
The web application itself is ASP.NET.
Because of the framesets, I can't simply use a HTTP redirect.
So far I have this Javascript code, which is registered as a startup script from within a class subclassing Page, where ... represents the redirection target URL:
((window.top == null) ? (window) : (window.top)).location = '...';
What bothers me is what MDN has to say about window.top and window.parent, respectively. Particularly, the documentation for window.parent spells out explicitly that
If a window does not have a parent, its parent property is a reference to itself.
which means that I can assert window.parent != null. But there is nothing similar about the value of window.top.
For the purposes of my question, you can assume that neither of these have been reassigned.
All that to lead up to the actual question: Does window.top make guarantees similar to that of window.parent? (I'm a bit concerned about the conditional expression. In my so far limited testing it works, but that doesn't prove it correct.)
As far as I can tell, at least MDN doesn't say for certain either way.

The HTML5 spec defines window.top like so:
The top IDL attribute on the Window object of a Document in a browsing context b must return the WindowProxy object of its top-level browsing context (which would be its own WindowProxy object if it was a top-level browsing context itself), if it has one, or its own WindowProxy object otherwise (e.g. if it was a detached nested browsing context).
So the top attribute must always refer to a window. The spec also defines top as readonly so it is not posisble to change it to point to something else (if the spec is implemented properly).
Something is very bad if window.top == null!

Related

Why is window.name cached?

in a programming challenge I recently took part in I had to use the window.name property to store / manipulate data. I found out that, when you change this property, it persists through page refreshes (although not when opening a new page with the same URL).
The only information I could find was that this is known and even used by some frameworks as data storage, but I would be interested in the why (as in why is window.name persistent? Any historical reasons?) and the how (which rules are there of when the window.name is kept between page changes and when it is discarded?).
Apparently, my Google-fu is not strong enough to find the answers to these questions (there is not even a mention of it on the MDN page!) so I hope that maybe you could help me.
My understanding of it is that the window object is persistent throughout the lifetime of a tab, and represents the window that is loading different HTML documents.
Each tab contains its own window object, which is why even when you navigate to/from different pages the window object is persistent, whereas if you check on a different tab the window.name will be different.
When opening different html pages, most of them do not override the window.name property, and it is completely optional. If nothing else is manipulating it, it will be what you leave it as. Most pages only touch on manipulating the window.document itself.
Named windows are used as link targets, for one:
some page
The link will open in a new window once, and in the same window if it still exists on subsequent clicks, with the window’s name being how it’s targeted.
The second argument of window.open is also a window name.
window.open('example.html', 'some_page');
You can try it out in your browser across unrelated websites; in one tab’s console, set window.name = 'test'; and in the other, use window.open('https://example.com/', 'test');. (You may have to let it through a pop-up blocker.) The unrelated tab should navigate to https://example.com/.

Window object and properties persistance

I know the Window object is the "master" object of the browser (tab) to which everything is appended - core methods, globally declared variables, functions, even the DOM. It is above everything.
When I go to a different page in the same browser window (tab) I suppose the window object remains the same (only the dom changes), because the history and other stuff is accessible. Why I don't quite grasp is why the global variables that are attached to the window object (even using window.myvariable) don't persist.
To me the only possible explanation is because it is made this way. If so what happens, do the "non core" window elements (methods and variables that were set by the code) get erased; is every new page visit a new instance of the window object (sounds the most obvious way to me) or ...?
I can't find any useful info on this matter, usually people only know that you can't pass variables between pages (except cookies, web storage, window title), but why/how (the mechanics, not reasons) this happens are hard to come by. Thanks.
Every tab in your browser is independent window object and has its own set of global variables and thus your assumption of sharing window object is not correct. Your javascript is not and should not be allowed to SEE between tabs. If that was possible then imagine one webpage you open sniffing data and other information between tabs. Your tabs are not allowed to do your browsing history sniffing ( they can get the length of the history, I think, though).
How can the browser be secure (If you are browser's vendor)?
First, it can chose not to support certain capabilities, period such as reading client's file system arbitrarily.
Second, restrict some of the features they provide.
You might want to take a look at Same-Origin Policy and certain restrictions that are relaxed that might be helpful.
All the global JavaScript variables, functions & objects automatically become member of the window object and they are persisted as long as the the new page is not loaded/visited in the same browser window (tab).
Whenever new page is loaded or we redirect to new page within same tab then scope of these functions and variables from previous document ends and they are removed from the window object. And globally declared variables and functions for newly loaded document (from scripts associated with document) gets attached to the window object

exceptions to same-origin policy

I know the same origin rule. I wonder if there is an exception such that a parent document script can read or write a child (iframe) document content but the latter cannot do it for the former, or viceversa (a iframe document script can read or write the parent document content but the latter cannot do the same).
What happens when one url is of data: type? Wikipedia is not so clear.
Two documents (i.e. frames) from the same origin can equally change one another.
If there are such exceptions, it is probably a browser specific behavior or a bug.
Wikipedia term described some behaviors that are well known (e.g. loading script from a different domain), and might been by-design. You can also change the window.name (read-write) or location (write-only) from one frame to another, even when the origins are different.
I do not know the quirks wrt data URIs.
To recap: even if you will find some odd exception - don't expect it to work across multiple browsers + browser versions. Better work on a more solid solution to your problem.

What defines the availability of the DOM `document` property in the javascript global object?

I am a bit new to javascript and was trying to understand how the W3C DOM standard and javascript as defined by ECMAscript interoperate.
Specifically, as I understand it:
the ECMAscript standard defines the existence of a Global Object, which provides functions such as parseInt(string) and explicitly allows the presence of other built-in objects accessible through it, but the definition of these is left to the implementation.
The W3C DOM standard defines a set of objects and interfaces which correspond to the structure of an HTML document. One of these is the Document object (uppercase D) containing methods such as getElementById. However this specification, as far as I understand it, does not define how an instance of such an object representing the current document in a browser may be obtained.
Basically, what I am after is - where is it explicitly stated that when executing javascript in a web page, I can call document.getElementById("someId") (note lowercase d), and that the document property represents the DOM of the document in which the javascript is executing?
Is this particular detail implementation-specific. Shouldn't it be standardised somewhere? The nearest I can get is the Gecko DOM documentation which appears to imply that document and Document are equivalent. I thought javascript was case sensitive? Or am I just being really anal about interpreting these things?
Edit:
Trawling through the HTML 5 standard working draft after Jason's comment, I think the bit that captures what I'm looking for is
6.5.3.3 Creating scripts
...the user agent must run the following steps:
4. Set up the script's global object, the script's browsing context, the script's URL character encoding and the script's base URL
6.5.3.1 states of the global object that
"This is typically a Window object. In JavaScript, this corresponds to the global object."
Further, 6.1 Browsing Contexts states
"The main view through which a user primarily interacts with a user agent is the default view. The AbstractView object that represents this view must also implement the Window interface, and is referred to as the Document's Window object. WindowProxy objects forward everything to the active document's default view's Window object."
Since the AbstractView interface implements the document property as per DOM 2 Views spec, this presumably is what defines the existence of the Javascript global document property.
This is informally called "DOM level 0" and it has never been standardized, despite being stable for a decade and more.
window, document, and so on will be standardized in HTML 5 (a forthcoming W3C standard).
As for case-sensitivity: Document is the name of an interface. It's a type. document instanceof Document is true.
HTMLDocument is another interface. document instanceof HTMLDocument is true, too.
This may not help but my understanding of what you are asking says you are getting a little confused between and instance of and object and the Object itself.
When you call document.getElementById("someId") you are making a call to the instantiated object named document which is an instance of the object Document. This is such that if you execute document instanceof Document it will return true.
I don't know if the standard states that a browser will create an instance of the Document element or when it does though as I have never read the spec.

What does XPCSafeJSObjectWrapper do?

What does Mozilla Firefox's XPCSafeJSObject wrapper actually do?
MDC's documentation is as follows:
This wrapper was created to address some problems with XPCNativeWrapper. In particular, some extensions want to be able to safely access non-natively-implemented content defined objects (and to access the underlying JavaScript object under an XPCNativeWrapper without its strong behavior guarantees). XPCSJOW act as a buffer between the chrome code.
This doesn't tell me a lot. In particular, I can't tell how accessing objects via XPCSafeObject is any different to accessing them directly.
Edit: I understand that the purpose of the wrappers in general is to protect privileged code from unprivileged code. What I don't understand (and doesn't seem to be documented) is how exactly XPCSafeJSObject does this.
Does it just drop privileges before accessing a property?
Actually XPCSafeJSObjectWrapper is used for all content objects, including windows and documents (which is in fact where it's most usually needed.) I believe it was invented mainly to stop XSS attacks automatically turning into privilege escalation attacks (by doing XSS against the browser itself). At least now if an XSS attack is found (and people will unfortunately keep looking) it doesn't compromise the whole browser. It's a natural development from the XPCNativeWrapper which was originally a manual (and therefore prone to accidental misuse by extensions) way for the browser to defend itself from XSS attacks.
The wrapper just ensures that any code that gets evaluated gets evaluated without chrome privileges. Accessing objects directly without this wrapper can allow for code to run with chrome privileges, which then lets that code do just about anything.
The purpose of the wrappers in general is to protect Privileged code when interacting with unprivileged code. The author of the unprivileged code might redefine a JavaScript object to do something malicious, like redefine the getter of a property to execute something bad as a side effect. When the privileged code tries to access the property it would execute the bad code as privileged code. The wrapper prevents this. This page describes the idea.
XPCSafeJSObject provide a wrapper for non-natively implemented JavaScript objects (i.e. not window, document, etc. but user defined objects.)
Edit: For how it's implemented, check out the source code (it's not loading completely for me at the moment.) Also search for XPCSafeJSObject on DXR for other relevant source files.

Categories

Resources