Chrome timeout for execution onbeforeunload handler - javascript

I need to implement a feature that checks for changed content before window close and display a predefined warning message if so.
What I did is simply register my handler as follows:
window.addEventListener("beforeunload", checkValueChanged, true);
In the very handler I initiate a synchronous request (using jsf.ajax.request()) to submit all pending data and calculate changes.
The whole solution seems to work pretty well for most cases, but when request takes a little bit longer (300ms?) the browser brutally kills the script without waiting for the response.
It happens only for Chrome (tested on 48.0.2564.116 m) - FF and IE waits for the request to complete. What`s more when I enable developer tools in Chrome it also works.
I suspect that this is an intended Chrome behavior based on a fixed timeout for onbeforeunload handlers execution time designed to protect user from various tricks and hacks on some sites (especially in porno ones :)).
My question is: have you ever encountered and handled somehow such situation? Is this "feature" documented somewhere in Chrome documentation or maybe its a bug? If its a feature can it be locally reconfigured or disabled?
I will be grateful for any hints :)

Related

Chrome V80 features to be deprecated

Starting from Chrome V80, few events like beforeunload, unload etc are getting deprecated. How would we handle such existing events further in JavaScript?
My requirement is to alert when user tries to refresh / reload the page (F5 or ctrl+r) or browser back button, I need to alert and on confirmation, I need to reload or move back. This is in JSF2.2
But the behavior should not effect the functioning in other browsers.
Can someone please help me with this
The beforeunload event will still be usable. What's being changed is the ability to perform sync XHR during page dismissal. The real harmful thing which will be deprecated in the long term is synchronous XHR, since it hurts the user experience. You'll still be able to make use of beforeunload. Getting Rid of Synchronous XHRs specifically mentions this:
Note: We expect to remove support for synchronous use of XMLHTTPRequest() during page unloads in Chrome in version 80, scheduled to ship early in 2020.
There's also information about this specific change in Chrome Platform Status: Disallow sync XHR in page dismissal. There's more information about Chrome 80 in Deprecations and removals in Chrome 80:
Chrome now disallows synchronous calls to XMLHTTPRequest() during page dismissal when the page is being navigated away from or is closed by the user. This applies to beforeunload, unload, pagehide, and visibilitychange.
To ensure that data is sent to the server when a page unloads, we recommend sendBeacon() or Fetch keep-alive. For now, enterprise users can use the AllowSyncXHRInPageDismissal policy flag and developers can use the origin trial flag allow-sync-xhr-in-page-dismissal to allow synchronous XHR requests during page unload. This is a temporary "opt-out" measure, and we expect to remove this flag in Chrome 82.
Note that popups during page dismissal will also be disallowed:
Pages may no longer use window.open() to open a new page during unload. The Chrome popup blocker already prohibited this, but now it is prohibited whether or not the popup blocker is enabled.

Browser console to set document.location.href and react on page load

Background / use case
I would like to automate some page interactions by pasting a script into my browser console (normally Chrome/Chromium or in my case IE11 because.. don't ask.)
Typical steps in one iteration:
(initial) Visit a page, wait until it is fully loaded.
Fill in form values automatically, trigger some buttons, submit.
Wait for new page after form submission.
Go to 'next page', wait until it is fully loaded, start over with a new set of form values.
The "Visit a page" or "Go to 'next page'" could either happen by clicking a button, or by setting document.location.href explicitly.
The "wait for ..." can take up to 30 seconds in both cases. Not for any good reason, just because.
I am aware (to my current understanding) that the js (event listeners etc) included in a page does not survive a new page load. I am specifically asking about js called form the browser's developer console.
Question
How can I register an event listener from the console for "page load complete" after setting document.location.href, or doing something equivalent?
As mentioned, in my use case I would need to do this with Internet Explorer 11. But I assume people are more familiar with the developer tools in Chromium or Firefox. Any answer that works in one of these browsers is welcome, just mention which browser you tried this with.
Limitations
I do not control the web application where I want to do this, I only control my browser. It also does not look like the developers of said application would be likely to respond to feature requests or wishes.
Perhaps someone will suggest to do this with an iframe. I am not sure this will work. If it does, this would be a different question.
Perhaps someone will suggest some kind of browser simulator tool to use instead of the console. Unfortunately I need/want to make this work on Internet Explorer in a corporate Windows environment with limited privileges. Alternative tools can be mentioned, but there is a reason why I focus on browser console.

How to deal with the overlay Paused in debugger while automated test execution using Selenium

Everytime I try to access this website and open google-chrome-devtools I am unable to inspect any of the elements through the Inspector as the UI is having an overlay along with a message Paused in debugger.
The upvoted and accepted answer of this discussion says to check the Source tab, check under the Event Listener Breakpoints panel if you've set any breakpoints under 'Mouse'. I have cross checked that none of the Sources -> EventListenerBreakpoint are set.
The upvoted and accepted answer of this discussion says to check if the little octagonal stop/pause sign (at lower left of Chrome "Sources") is colored (blue or purple). I am not sure why do I need to do that additionally for selected websites.
Snapshot:
The upvoted and accepted answer of this discussion speaks about the Manual Steps.
All the solutions seem to point towards the manual process. But this issue seems to me the root cause behind Selenium being unable to getPageSource().
Code trials:
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.addArguments("disable-infobars");
options.addArguments("--disable-extensions");
WebDriver driver = new ChromeDriver(options);
driver.get("http://rd.huangpuqu.sh.cn/website/html/shprd/shprd_tpxw/List/list_0.htm");
Output: Chrome opens but doesn't navigates to the url.
So my questions are:
In which case can Paused in debugger error occurs?
Is it an error from the frontend development?
How can I bypass this error during the Automated Tests through Selenium?
In which cases can the Paused in debugger error occur?
Anytime you are accessing this page with the dev tools open. The debugger; line will pause javascript execution, but browsers will ignore it if the dev tools are closed.
Is it an error from the frontend development?
In this case, no--they're deliberately trying to keep you out. The purpose of this function is to pause execution and then redirect your browser to a different page if it takes longer than 100ms to resume. I would speculate that this is designed to interfere with automated crawlers like selenium, because a regular user wouldn't be affected and a human developer can just hack around it.
How can I bypass this error during the Automated Tests through Selenium?
My first recommendation would be to try running Selenium headlessly, if that's an option. If not, use the hotkey to resume execution (F8). You can use whatever method you like for generating a keypress; with the java.awt package it will look something like this:
Robot robot = null;
try
{
robot = new Robot();
}
catch(Exception e)
{
//handle failure
}
robot.keyPress(KeyEvent.VK_F8);
Remember that you have to trigger this within 100ms, so use whatever logic you like to detect the block and respond quickly. If you just want something quick and dirty, I would just make it spam F8 keypresses every 50ms for a period of time until you're certain the page has loaded.
EDIT: On further investigation, this page is extremely messy and hostile to anyone with the dev tools open. There is not one but several functions that trigger debugger;and they get called repeatedly on a timer for as long as you're on the page. Running headlessly seems like the best choice, unless you want to continue spamming F8 for the entire session.

Angular application throws HTTP 0 in Firefox when page is quickly refreshed

I'm working on an angular application and came across the bug that in Firefox, if we refresh quickly enough (often takes several times) the page will eventually fail to load and, in my case, displays an HTTP 0 error code, which if I'm not mistaken means that an AJAX call was canceled before receiving the response from the server.
I have not seen this behavior in Chrome or IE, but I don't know if that's because the JS engines in those browsers are helping me out, or if it's a browser bug itself (in Chrome at least it appears that the refresh button for a page is disabled while requests are being made on page load).
Is there a Firefox bug, an angular bug, or a bug in my application? If it's the later, how can I avoid this?

Chrome extension action on shutdown

I'm writing a very simple Chrome extension to automatically clear my history as this isn't a built in feature. I've got it functional but just want to confirm I've done things that make sense before I wrap it up.
First - is there a reason to do a chrome.history.deleteAll? This doesn't actually appear to interface with URL browsing history, instead you need to use chrome.browsingData.* for that. Should I do the former anyway?
Next - after searching and searching, there appears to be no way to execute a function on shutdown. The closest I got to real info on this was someone saying when Chrome quits it terminates all extensions without prejudice. Am I missing a way to clean up history on shutdown?
Finally - as I can't cleanup on shutdown, I'm cleaning up on startup, using window.onload in the background page. chrome.runtime.onStartup did not reliably work for me while window.onload did - is this an okay way to do things?
Thanks in advance for any help.
you are right, there's no way to execute anything on Chrome shutdown. Chrome doesn't have an onClose event. Not only literally, but metaphorically speaking: When Chrome closes, it doesn't wait for any extension to close.
You can hang from chrome.windows.onRemoved and wait for the last window to close, but if Chrome is shutting down, it's not guaranteed your extension will have time to run it. Same thing with onSuspend, or whatever you find.
So, if your implementation works, it won't be guaranteed to work in other Chrome.
About chrome.history.deleteAll, I have the same problem, and will try with chrome.browsingData, a more modern and complete way to deal with browsing data, including history.
This document lists an onSuspend event:
Clean-up before app closes
The app runtime sends the onSuspend() event to the event page before
unloading it. Your event page can listen out for this event and do
clean-up tasks before the app closes.
Once this event is fired, the app runtime starts the process of
closing the app: all events stop firing and JavaScript execution is
halted. Any asynchronous operations started while handling this event
are not guaranteed to complete. Keep the clean-up tasks synchronous
and simple.
chrome.runtime.onSuspend.addListener(function() { // Do some simple
clean-up tasks. });
This document says the onSuspend is also available for extensions

Categories

Resources