I'm doing an application where one window needs to talk to another, even though they didn't originally come from a common page. There seems to be a requirement in Chrome that this is so.
The two windows are from the same domain, which I control, but one might be launched from a bookmark and the other from an Excel worksheet.
I've got a demo here:
http://cfpreview12.dmclub.net/Frametest/europe.htm
Go to that URL (with Chrome)
- Launch France
- Launch Germany
- Click on "Go to Paris"
and it works (because France and Germany had a common referrer).
Now copy the URL of the France tab, close the tab, create a new tab
manually and paste back the URL.
When you then flick back to Germany and click on "Go to Paris", a NEW TAB is created, seemingly because Chrome doesn't see the relation between windows that don't have a
shared heritage.
I have full control over both pages (France and Germany) but in the real
use, there is no such thing as Europe.
Any ideas on workarounds?
You won't be able to use target directly; you'll have to do navigations from the JavaScript in each context, sending messages from the scripts in each different window between each other.
OK, so how do we get scripts in different windows (but the same domain) to communication when they don't have a shared reference to a window?
The old-school way, write values to document.cookie and they will be visible to scripts on other windows in the same domain. Requires some annoying protocol overhead in polling for cookie changes, acknowledging receipt/deleting, and encoding long messages (as cookie lengths are limited).
The slightly better version of the same thing using localStorage instead of cookies where available - avoids polluting the cookie header and increases the length of data that can go in a single message.
The modern way - create a SharedWorker and communicate with it from each window. Unfortunately limited availability at present.
You can of course fall back from (3) to (2) to (1) as necessary.
Related
I'm tasked with coming up with a way to determine if a person has reached our site via using their back button (meaning they left our site and came back) and log them out if so.
I've come up with some options, but am wondering what other options I may be missing.
FYI, we do have a session state, so server-side we're covered for long absences, but they want an additional check on the client side.
option 1: set a cooking via onunload that expires in x seconds. On each page of our site, I check for said cookie. If it exists, I assume they came from another page on our site and do nothing. If it's not there, I assume they have been gone from our site more more than x seconds and redirect out. Con: Blackberry devices running OS5 don't support onunload.
option 2: same as #1 but instead of setting cookie onunload, we set it on every click of every link that goes to another page on our site. con: messy
option 3: check browser history on every load of every page of our site. If the previous URL is not one of ours, we log them out. Cons: browser support? It looks like previous/next history objects are now blocked in modern browsers due to security.
Option 4: Via JS, every x seconds, check for a cookie. If it's there, reset it to expire in x seconds. If it's not there, assume they've returned from somewhere else. Con: Not sure if the JS cookies would be set while that page may be in the background (app switching on an iPhone, or using a different tab in a desktop browser).
Any other options I should consider? Is there a 'proper' way to handle this? Is this just grasping at straws trying to prevent normal browser behavior?
You could keep the current page name/action/identifier in a session variable, then use a javascript onChange/load/keyup/keydown to request the current state of the user from the server. If it does not match, redirect or otherwise block them from viewing the current page.
This is a method that I've used, but it has it's downsides.... for example, onload doesn't always seem to work when the user uses the back button. OnChange, etc on certain form fields definitely works. Timers are pretty straightforward, as well, but a quick user can get input through the page regardless.
It's not that complicated... Use javascript history object
history.next gives you the complete url of the page in the forward button. A simple regex can tell if it's from your domain or not.
I just don't know if it's supported by all browsers
When a page is iframed or included as part of a frameset, it can use Javascript to check so. (i think usually by
if (self != top) top.location.href = self.location.href;
). Can the page always "jump back out" like that when Javascript is enabled? Is there a way to not let it jump back out? (suppose my page is iframing that page).
(in another scenario, i think if we use window.open() to open the page in a new windoe, then the page almost always cannot refuse... unless they check the referrer and actually refuse to serve the page even if it is a new, standalone window).
As far as I know, there is only one way - a Microsoft proprietary extension to HTML that allows an iframe start tag to specify that the page should be loaded with reduced security privileges - which usually blocks JS from running in it.
Happily other browsers do not support this feature.
Perhaps you can check out the window.location.href property. If it matches, then let your page load. Else, stop!
There is some interesting work being done at Carlton University that was presented at CCS called SOMA (Same Origin Mutual Approval) which basically presents a model for content inclusion (ala iframes) where both parties must approve of the inclusion for the browser to go through with it.
Unfortunately it's still in its early stages, and although they've already developed a Firefox addon, it needs to gain traction in the web development community and native browser support before it's viable.
It's still cool to check out though: http://www.ccsl.carleton.ca/software/soma/
Without any special extension or hacks to the browser, the framed page can choose to break out of the frame by reloading itself into the top frame.
Personally, I feel that attempting to block a framed page from breaking out of the frame is bad netiquette.
We have a product that has both a winforms and a web client, and are providing the users a way to launch into another company asset (a web application). We need to make sure that the user only ever has one instance of the other web application open in a browser (or at least that we've opened for them). We accomplished this (sort of) by doing the following...
In the winforms client, we have a hidden WebBrowser control that, when the user clicks the button to launch the other app, we write a small HTML page into the DocumentText property that contains:
window.open('http://othersiteurl', '**sitename**').focus();
In our web client when the user clicks on the same button we do something similar:
window.open('http://othersiteurl', '**sitename**');
From only one client or the other this works surprisingly well. Where things get sticky and weird is when you try accessing it from both clients. If you launch the other product from the winforms app first, it launches a new window, and any subsequent launches of the product from either client load in the instance that's already open. But if you do it the other way around, and start from the web client, the first instance launches in a new tab in the same window, but then every launch from the winforms client goes to a new window!
I'm using the same value for the 'name' parameter of the window.open in both clients. It's bizarre to see it work so horribly different. Can anyone explain how the 'name' parameter is scoped in IE? (yes, this is IE-only...the WebBrowser control hosts IE, and our product is IE-only) When launching from the winforms client first it seems to be global to all open instances, but the other way around makes it seem very much the opposite.
Any ideas?
Have you tried window.createPopup? Dunno if it would work any better, but if you don't need the "chrome" it might be worth a shot. For more info check out the MSDN:
http://msdn.microsoft.com/en-us/library/ms537638(VS.85).aspx
Under IE7, and prior versions as well to my knowledge, the name parameters is scoped to a particular instance of the IE process. Typically, starting IE manually creates a new process. Any windows that are created via js or even clicking the "New Window" button within IE, creates a new window that is still running under the current process. Under this condition, the name is in scope across these windows.
When you have a desktop application spawn an instance in the way you mention, it is opened under a new process. Depending on the framework (.NET, etc) it may reuse the process once it has a handle to the first, or it may create a new process for each call. It sounds like, from your initial testing, that the first is the case, where the application will reuse the process.
That being said, I am not sure what kind of process you may have to implement to check for the name "cross-process". One option, depending on what kind of control you have over the web application they are accessing, could be to have the server keep track of a list of user to session ids and when a second entry shows up for a user, that means they have a second browser open, and handle appropriately from there.
I'm having a few problems with an application that integrates sharepoint, SQL reporting services and a bunch of custom forms that are built using ASP.NET MVC.
Assuming my servers are as follows;
MOSS
SSRS
Custom forms
In MOSS, my portal has need on occassion to popup a custom form to capture user input. I've done this by using a jQuery dialog (using Boxy), which iframes the custom form in and passes the url of the portal into it. When the custom form is finished, it navigates the parent window (the MOSS portal) to the URL passed in, which effectively refreshes the page.
This was working fine until we threw in the complexity of SSRS.
Now in MOSS, I have a report that lists some data, but the SSRS report viewer web part seems to iframe it's report content in, which means the hyperlinks from the report can't ask the parent to overlay the same dialogs (as it's cross domain) and if it were to perform the overlay itself, it would just overlay the iframe.
Sorry for the long post, getting to the point - this is an internal intranet application only. Is it possible to allow cross domain scripting somehow so that the popup dialogs can all be controlled from javascript within the sharepoint portal and SSRS and my custom forms can just invoke javascript methods on the parent?
Preferably I wouldn't want to have to do configuration in the client browser to allow this to happen, as I'd have to roll that change out to all the machines within the estate - which is a significant number.
Thanks in advance, beer available to anyone who can solve my woes ;)
Cheers,
Tony
IE8, Firefox 3, recent Opera and Safari/Chrome support postMessage which allows cooperating pages on different domains to talk to each other:
http://ajaxian.com/archives/cross-window-messaging-with-html-5-postmessage
If you are stuck with older browsers, you have few options. The cleanest is to send everything that needs to communicate with each other through the same proxy, although in the OP's situation it looks like this isn't possible.
The next cleanest is to use Flash's cross-domain facility.
Another option is xssinterface, which wraps postMessage where available and uses some voodoo involving cookies and polling where it isn't.
The only other option is to use hidden iframes - to send a message to a page, change the iframe's location to one on the destination page's domain and poll in the destination page - but again I think the proxying in the OP's case makes this unworkable.
There is another option in addition to those Andrew provides. You can dynamically inject script tags into the DOM, wherein the src attribute can point to a javascript file on any domain.
In jQuery you accomplish this by specifying "jsonp" as the datatype for the ajax request. You can read more about this approach here:
http://blog.ropardo.ro/2009/09/23/cross-domain-ajax-calls/
I finally got around these issues by using hidden iframes as suggested. I posted an article on my blog with more details and pushed the code onto codeplex:
http://www.deepcode.co.uk/2009/11/overcoming-cross-domain-issues-between.html
I am opening a new window from a button using var myWindow = window.open(...). I then want to move that window to the correct location on the screen. I use myWindow.moveTo(10,10) to do this but I get an Access Denied error.
The window I open contains information from another server to the one I am executing on. When it isn't, the window moves correctly. Is this the limitation and is there a way around it?
I am using IE7. (The work is for an existing Intranet that includes lots of ActiveX so all users use IE7)
You could try to put the information from the other site in an iframe located on the same host that runs the window.open JavaScript. Or maybe even better, get the information server-side and present it directly from your site. Iframes can be trouble.
The window I open contains information from another server to the one I am executing on. When it isn't, the window moves correctly. Is this the limitation and is there a way around it?
Browsers security model have been increasingly restrictive over the last couple of years. What you could do a few years ago, isn't allowed any more. Blame it on advertising companies.