I have a piece of code which works in a way that is unexpected to me. Let me first put down the details, so the code looks more or less like this:
window.onunload = doUnload;
var unLoadTimer;
var gInvokeOnBeforeUnload = true;
function setInvokeOnBeforeUnload() { gInvokeOnBeforeUnload = false; }
function doUnload() {
if(gInvokeOnBeforeUnload==true){
setInvokeOnBeforeUnload();
top.document.location.href = "LogOff";
clearTimeout(unLoadTimer);
}
//Function Midpoint
if (top.document.readyState != "complete" && gLogOffClick == false){
unLoadTimer = setTimeout("doRealUnload("+func_call_count+")", 800);
//its just a timeout for the function to be called again
}
}
How I also added logging but for sake of keeping code small excluded from examples. The issue I faced was that top.document.location.href is NOT reassigned to "LogOff" and is still equal to the very first starting page I opened on the site, call it "LogIn".
To trigger the window.onunload event I hit F5 (and it happens all the time), but the logoff is not assigned to location.href. Only if at "//Function Midpoint" comment marker I add a simple alert(1); then logoff is triggered (as seen in Apache logs below), however location href is still the same as it was - "LogIn".
Am I wrong to assume it should change as soon as its assigned a value?
And so I'm failing to understand several points:
Why location.href is not changed as soon as I assign it the value of LOGOFF.
What should happen as soon as LOCATION.HREF is changed
How does LOCATION.HREF get initialized when I open the browser and logon
Don't have any fancy session tracking mechanisms, its a straight forward HTML page with the above JS triggered # onunload via F5.
All I want to achieve is to understand what happens behind the scenes and why the redirect happens if there is an alert(1); inbetween and doesn't if no break is there. In my case Apache registered the following:
With timeout:
IP.IP.IP.IP - xxx [28/Oct/2011:10:38:50] "GET /LogOff HTTP/1.1" 200 208
IP.IP.IP.IP - xxx [28/Oct/2011:10:38:50] "GET /LogIn HTTP/1.1" 401 540
IP.IP.IP.IP - xxx [28/Oct/2011:10:38:52] "GET /LogIn HTTP/1.1" 200 2898
Without timeout:
IP.IP.IP.IP - xxx [28/Oct/2011:10:41:04] "GET /LogIn HTTP/1.1" 200 2726
Any help or guidance towards what to read/where to look is appreciated, even better if someone could elaborate what happens behind the scenes. Im afraid I'm not well educated in JS engines, to my disadvantage. The code is also not really mine :(
If you have extra question I'm listening, maybe I omitted something important there :)
Didn't try to test in other browsers as IE is the only focus group I need...
document.location.href is read-only when unloading the page. Hence you are not allowed to change this property when the user wants to leave the page. This is a security 'feature'.
See also: Changing window.location.href in Firefox in response to an onunload event
I suggest you instead make an asynchronous call to the server, logging out the user etc. You can do this with an Ajax-call, which is fairly simple using jQuery.
Related
So I have a system that essentially enabled communication between two computers, and uses a WebRTC framework to achieve this:
"The Host": This is the control computer, and clients connect to this. They control the clients window.
"The Client": The is the user on the other end. They are having their window controlled by the server.
What I mean by control, is that the host can:
change CSS on the clients open window.
control the URL of an iframe on the clients open window
There are variations on these but essentially thats the amount of control there is.
When "the client" logs in, the host sends a web address to the client. This web address will then be displayed in an iframe, as such:
$('#iframe_id').attr("src", URL);
there is also the ability to send a new web address to the client, in the form of a message. The same code is used above in order to navigate to that URL.
The problem I am having is that on, roughly 1 in 4 computers the iframe doesn't actually load. It either displays a white screen, or it shows the little "page could not be displayed" icon:
I have been unable to reliably duplicate this bug
I have not seen a clear pattern between computers that can and cannot view the iframe content.
All clients are running google chrome, most on an apple powermac. The only semi-link I have made is that windows computers seem slightly more susceptible to it, but not in a way I can reproduce. Sometimes refreshing the page works...
Are there any known bugs that could possibly cause this to happen? I have read about iframe white flashes but I am confident it isn't that issue. I am confident it isn't a problem with jQuery loading because that produces issues before this and would be easy to spot.
Thanks so much.
Alex
edit: Ok so here is the code that is collecting data from the server. Upon inspection the data being received is correct.
conn.on('data', function(data) {
var data_array = JSON.parse(data);
console.log(data_array);
// initialisation
if(data_array.type=='init' && inititated === false) {
if(data_array.duration > 0) {
set_timeleft(data_array.duration); // how long is the exam? (minutes)
} else {
$('#connection_remainingtime').html('No limits');
}
$('#content_frame').attr("src", data_array.uri); // url to navigate to
//timestarted = data_array.start.replace(/ /g,''); // start time
ob = data_array.ob; // is it open book? Doesnt do anything really... why use it if it isnt open book?
snd = data_array.snd; // is sound allowed?
inititated = true;
}
}
It is definitele trying to make the iframe navigate somewhere as when the client launches the iframe changes - its trying to load something but failing.
EDIT: Update on this issue: It does actually work, just not with google forms. And again it isn't everybody's computers, it is only a few people. If they navigate elsewhere (http://www.bit-tech.net for example) then it works just fine.
** FURTHER UPDATE **: It seems on the ones that fail, there is an 'X-Frames-Origin' issue, in that its set the 'SAMEORIGIN'. I dont understand why some students would get this problem and some wouldn't... surely it depends upon the page you are navigating to, and if one person can get it all should be able to?
So the problem here was that the students were trying to load this behind a proxy server which has an issue with cookies. Although the site does not use cookies, the proxy does, and when the student had blocked "third party cookies" in their settings then the proxy was not allowing the site to load.
Simply allowed cookies and it worked :)
iframes are one of the last things to load in the DOM, so wrap your iframe dependent code in this:
document.getElementById('content_frame').onload = function() {...}
If that doesn't work then it's the document within the iframe. If you own the page inside the iframe then you have options. If not...setTimeout? Or window.onload...?
SNIPPET
conn.on('data', function(data) {
var data_array = JSON.parse(data);
console.log(data_array);
// initialisation
if (data_array.type == 'init' && inititated === false) {
if (data_array.duration > 0) {
set_timeleft(data_array.duration); // how long is the exam? (minutes)
} else {
$('#connection_remainingtime').html('No limits');
}
document.getElementById('content_frame').onload = function() {
$('#content_frame').attr("src", data_array.uri); // url to navigate to
//timestarted = data_array.start.replace(/ /g,''); // start time
ob = data_array.ob; // is it open book? Doesnt do anything really... why use it if it isnt open book?
snd = data_array.snd; // is sound allowed?
inititated = true;
}
}
}
After a new install of Firefox 45 Developer Edition, I saw this page. It has a button ("Let's do it") that when clicked, somehow opens up the Choose default apps settings page in Windows 10.
https://www.mozilla.org/en-US/firefox/windows-10/welcome/?utm_source=firefox-browser&utm_medium=firefox-browser
How is this done? I couldn't find anything through the Developer Console in the labyrinthine code on that page. Besides, I would have thought browsers don't allow JavaScript to open something as sensitive as the Settings app.
The page fires a custom event of type mozUITour on the document. This event is handled in the browser by content-UITour.js, which shovels out most of the actual processing to UITour.jsm. The unobfuscated client-side code can be viewed in UITour-lib.js.
Cutting through all the client-side abstraction, this is what’s happening:
document.dispatchEvent(new CustomEvent('mozUITour', {
bubbles: true,
detail: {
action: 'setConfiguration',
data: {
configuration: 'defaultBrowser'
}
}
}));
Then in the browser, it handles the event, dispatches the event in another internal event queue, where it will be processed by calling into nsIShellService::setDefaultBrowser, implemented by nsWindowsShellService.cpp. On what’s currently line 943, we have:
if (IsWin10OrLater()) {
rv = LaunchModernSettingsDialogDefaultApps();
} else {
rv = LaunchControlPanelDefaultsSelectionUI();
}
And LaunchModernSettingsDialogDefaultApps, I think, is a pretty descriptive function name.
Now, from your comment, “in a way that one could use it on their own page, for example”? Not so likely. content-UITour.js checks that the page has the uitour permission. From browser/app/permissions, we have:
# UITour
origin uitour 1 https://www.mozilla.org
origin uitour 1 https://self-repair.mozilla.org
origin uitour 1 https://support.mozilla.org
origin uitour 1 about:home
So unless you’re www.mozilla.org, self-repair.mozilla.org, support.mozilla.org, or about:home, you can’t do it, at least not by default. Before Firefox 15 (17 with a manual settings change, see this bug for more information), you might be able to use netscape.security.PrivilegeManager.enablePrivilege to request extra permissions from the browser, but that’s not around any more, and I’m not sure that even touches the same permission mechanism.
Edit : this is the windows behaviour, with linux it just fails.
First, if you succeeded navigate on gmail with casper (without random waiting time -from 20sec to 5min-), please tell me.
I want to register on our site, then validate my registration automatically with Gmail (an entire register step). Did someone do that before?
I have no problem to register, and I can login on my mailbox (Gmail) but after i have some troubles to navigate and validate my registration in Gmail, and i observe different behaviors between phantomJS and slimerJS.
In phantom it will work (without special commands), but it may take until 5 minutes before pass in the next step (waitForSelector). And with slimerjs it just stays stuck on the mailbox page.
EDIT : A strange thing : if i click manually (slimer) on a link which opens a popup, it stops being blocked and my navigation continues, it's like it can't detect the end of the step itself and can't perform the waitFor after the submit click without another interaction. Is it a refresh/reload problem?
Try that to see yourself :
casper.thenOpen('https://accounts.google.com/ServiceLogin?service=mail&continue=https://mail.google.com/mail/&hl=en', function(){
this.sendKeys("input#Email","your mail");
this.sendKeys("input#Passwd","your password");
this.click("input#signIn.rc-button-submit");
console.log(this.getCurrentUrl());
this.waitForSelector(".aeF",function(){//fail with linux -> timeout
this.test.pass("ok"); //windows -> stuck in slimer, several times in phantom
this.test.assertExists(".T-I.J-J5-Ji.T-I-KE.L3","Gmail Home ok");
console.log("url "+this.getCurrentUrl());
});
And i don't get any timeOut error. In slimerjs it just keeps the page opened.
If i do a waitForPopup instead of a waitForUrl, i have the error (timeout -> did not pop up), so why does a waitForUrl/waitForSelector... stay stuck ? I tried --web-security=no,--ignore-ssl-errors=true commands too (not linked but i tried --output-encoding=ISO 8859-1 too which doesn't work).
Here the differences between phantom and slimer (doc) :
http://docs.slimerjs.org/0.8/differences-with-phantomjs.html
(useless in this issue i think)
Well, we finally found a way to do it : the problem is by default gmail loop on ajax requests, to check some new mails, etc... see Page polls remote url, causing casper to block in step.
Fortunately google proposes a way to avoid that, using the simplified HTML version (you can for example use a special gmail address for your tests using this version) :
That way the script works as it should.
Bonus :
/*
* Click on an element specified by its selector and a part of its text content.
* This method resolves some problem as random space in textNode / more flexible too.
* Need to fix one bug though : when there is a tag in textContent of our selector.
*/
casper.clickSelectorHasText = function (selector, containsText){
var tmp = this.getElementsInfo(selector)
,i
,l
,bool=false
;
for (i=0,l=tmp.length;i<l; i++){
if(tmp[i].text && tmp[i].text.indexOf(containsText)!==-1){
this.clickLabel(tmp[i].text);
bool=true;
break;
}
}
casper.test.assert(bool, "clickSelectorHasText done, text and selector found -> click selector " + selector +" which contains text " + containsText);
};
casper.thenOpen('https://accounts.google.com/ServiceLogin?service=mail&continue=https://mail.google.com/mail/&hl=en', function scrapeCode(){
//log in
this.sendKeys("input#Email","your email");
this.sendKeys("input#Passwd","your password");
this.click("input#signIn.rc-button-submit");
//wait to redirect to our mailbox
this.waitForSelector("form[name='f']",function(){
//check main block
this.test.assertExists("form[name='f']","Gmail Home ok");
this.test.assertSelectorHasText("span", "Your gmail title message");
this.clickSelectorHasText("font", "one string which appears in font tag");
//wait inscription message appears
this.waitForSelector("div.msg",function(){
this.test.assertSelectorHasText("a","the message which activates your account--> in <a>");
});
})
//validate our account
.then(function(){
this.clickLabel("the message which activates your account--> in <a>");
this.waitForPopup(/mail/, function(){
this.test.pass("popup opened");
});
this.withPopup(/mail/, function(){
this.viewport(1400,800);
this.test.pass("With Popup");
//wait something on your website (for me selector .boxValid)
this.waitForSelector(".boxValid", function(){
/*
* Here your code after validation
*/
});
});
})
It might be possible to do it with normal gmail using event, see resource.received.
es.onmessage = function(e) {
var newElement = document.createElement("li");
newElement.innerHTML = e.data;
eventList.appendChild(newElement);
};
es.onerror = function(e) {
**//what to add here to ensure I don't miss events sent during this time frame, or state**
};
There are situations in the communication between the browser and the client where the server is pushing data as I see in the server log but the client doesn't display it. See a snapshot below
127.0.0.1 - - [06/Mar/2014 21:31:23] "GET /updates/1 HTTP/1.1" 200 - 60.2671
As you can see the URL /updates/1 is the EventSource(url) that I use and 60.2671 is the seconds. Is this bad that this is such a long request or is it supposed to be that way.
This problem is solved I modified my code to add the line
EventMachine::PeriodicTimer.new(20) { out << "data: \n\n" } # required, otherwise the connection is closed in 30-60 sec
Adding this line ensures that the persistent connection that you keep_open stays open for as long as possible. Otherwise it times out and then reconnects causing events being missed.
I have following problem: No log pessage shows me in every console (builder's console absolutely useless - nothing happened at all when I click, built-in FF console shows every info about installing, uninstalling etc, Firebug shows nothing).
I used console.log(), console.error() without success.
On about:config page is every logLevel's set to 'all' and devtools.errorconsole.enabled is also true.
Please help me, I'm desperate :-(
Thank you.
Kamil
PS: log window is bellow. There are 3 css errors (by default 'cause I don't include any css file - it's something about expected declarations and skipped to next declaration). Program code is simple console.log('test') or console.error('test') inside or outside exports.main = function().
17:34:52.086 GET https://builder.addons.mozilla.org/get_latest_revision_number/1127553/ [HTTP/1.1 200 OK 207ms]
17:34:52.086 GET https://builder.addons.mozilla.org/package/check_latest_dependencies/1835317/ [HTTP/1.1 200 OK 215ms]
17:34:52.088 POST https://builder.addons.mozilla.org/xpi/prepare_test/1835317/ [HTTP/1.1 200 OK 805ms]
17:34:52.862 "XPI delayed ... try to load every 2 seconds" ide-min.js:1
17:34:53.919 GET https://builder.addons.mozilla.org/xpi/test/2dnzeahpy6adc/ [HTTP/1.1 200 OK 1494ms]
17:34:53.865 "installing from /xpi/test/2dnzeahpy6adc/" ide-min.js:1
17:34:54.863 "request is running" ide-min.js:1
17:34:56.308 Očakávaná deklarácia, ale bolo nájdené '['. Preskočené na ďalšiu deklaráciu. latest
17:34:56.309 "Add-on installed" ide-min.js:1
17:34:56.326 Chyba pri spracovaní hodnoty pre 'opacity'. Deklarácia vynechaná. latest
17:35:00.337 Chyba pri spracovaní hodnoty pre 'top'. Deklarácia vynechaná.
You have to change the logging level, which by default is error, either globally or for specific extensions.
See the related documentation.