One of my current projects is a Qt project that uses an embedded QWebEngineView
to handle some of
the UI logic. A part of the code base relies on a combination of the
QWebEnginePage::windowCloseRequested()
signal and the window.close()
javascript function to
capture certain close events. Strangely, there was a defect whereby calling window.close()
would
generally work but in certain circumstances it would stop working all together. The javascript
console would then output a standard warning that looked like this:
Scripts may close only the windows that were opened by it.
While this is a standard security protocol in the browser, it was perplexing to see it here as the security setting to allow scripts to close pages was allowed. Furthermore, this particular page was not created by a script as it was the index page of a single-page-application.
After having no luck figuring out the issue I became curious to understand what was happening in
the QWebEngineView
that was triggering this warning. Since the Qt Web Engine is based on chromium,
I grepped the source and found this:
Settings* settings = frame()->settings();
bool allowScriptsToCloseWindows = settings && settings->allowScriptsToCloseWindows();
if (!page->openedByDOM() && frame()->client()->backForwardLength() > 1 && !allowScriptsToCloseWindows) {
if (activeDocument) {
activeDocument->domWindow()->frameConsole()->addMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, "Scripts may close only the windows that were opened by it."));
}
return;
}
By process of elimination, I discovered that the offending check had to be frame()->client()->backForwardLength
.
After some experimenting I learned that the window.close()
error only occurred after I clicked on
an anchor tag which created a navigation event (i.e. increased backForwardLength()
by 1).
Supressing the default event prevented this issue.
CONCLUSION: When relying on the window.close()
event in chromium based projects, ensure that
the web client doesn't create a navigation event. Either avoid using anchor tags, forms, etc. or
supress the default behavior in javascript using something like preventDefault()
.