Window that was opened by window.open won't close - javascript

I'm having problems with a piece of code that has worked before for years, but seems to have stopped working now.
I'm opening a window with a login form and I'm listening via a WebSocket for events regarding that login. After the login was successful, I want to close the window (that my script has opened and kept the reference to) after a short moment. I'm using the following code:
const windowManager = {
window: null,
eventType: null,
}
function openWindow({ url, eventType }) {
windowManager.window = window.open(url)
windowManager.eventType = eventType
}
function closeWindow({ eventType }) {
if (windowManager.window && windowManager.eventType == eventType) {
setTimeout(() => {
windowManager.window && windowManager.window.close()
windowManager.window = null
}, 100)
}
}
I have confirmed that windowManager.window.close() is called and does not thrown an error. I have also extracted the code from the application and tested it separately and it still won't close the window. As I said, this piece of code has worked before and was not changed in the past two years or so.
I'm using the following browsers:
Safari 15.3
Firefox 97.0b9 (Developer Edition)
Chromium 94.0.4606.61
I'm grateful for any pointers which could help resolve this issue. Thanks a lot!

After figuring out that the above code worked totally fine with other sites like Google or GitHub, I found that the Cross-Origin-Opener-Policy header in our auth backend (which was the site that was opened with the code) is the culprit. We had just updated Helmet to version 5 which added the header by default.
Our solution was to set Cross-Origin-Opener-Policy to same-origin-allow-popups on both source and target window (which are hosted on the same origin, but served by different servers). It also worked when setting it to unsafe-none for the target window without setting it at all on the source window.

Related

Not allowed to launch cutom protocol because a user gesture is required

I need to run my custom protocol twice but it doesn't work the second time, I got this error ( Not allowed to launch 'cutomProtocol' because user gesture is required. ) I tried to find a solution but I did not find any!
Same problem with chrome, firefox and edge.
I need to see this popup twice
window.location.href = 'my-protocol://${base64}';
and
customProtocolVerify(
`my-protocol://${base64}`,
() => {
// successCb: Callback function which gets called when custom protocol is found.
console.log('My protocol found and opened the file successfully..');
},
() => {
// failCb: Callback function which gets called when custom protocol not found.
console.log('My protocol not found.');
}
);
I tried with these two and didn't work
Clarification
I have a custom protocol.
My scenario:
check if it's installed successfully (I'm using customProtocolVerify method) and that method makes the launch if the protocol is found
run some APIs
launch the protocol again
My problem:
Step 3 doesn't work, I have the error on the console that says " Not allowed to launch... " and of course I can't see my popup to open my protocol.
I'm asking for help to make step 3 work
The only way to bypass this "bug" is to ask the user twice (or in a loop) by showing a OK alert or some sort of user confirm box.
My solution:
OpenLinkInExternalApp(Link);
alerty.alert('', { title: '', okLabel: 'Open Link' }, function () {
OpenLinkInExternalApp(Link);
});
The above code will open the external app, then a OK alert will pop up, after clicking OK, I call the same code again. Do this in a loop if needed.
TIP:
We guide our users to use split screen at this stage. This is where users can dock your web-app on the left and the external app on the right as an example.
Alert Box:
We user Alerty.js https://github.com/undead25/alerty#readme

How to disable switching to explorer activity bar when call openTextDocument? VScode

I'm creating an extension for vscode. At some point I need to open a file. I use vscode.workspace.openTextDocument for that and it's working, but switchs activity bar from custom to Explorer. I want to leave my custom activity bar opened. How can I do that?
I have tried closing all activity bars except mine, searching for some settings(nothing found), tried to use vscode.commands.executeCommand with workbench.view, but there are only workbenck.view.explorer and workbench.view.extensions.
select(node: json.Node) {
var setting: vscode.Uri = vscode.Uri.parse('file:///home/user/some_file');
vscode.workspace.openTextDocument(setting).then((a: vscode.TextDocument) => {
vscode.window.showTextDocument(a, 1, false).then(e => {
// move to 96 line in the file. Just for example.
let range_n = e.document.lineAt(96).range;
e.selection = new vscode.Selection(range_n.start, range_n.end);
e.revealRange(range_n);
})
}, (error: any) => {
console.error(error);
debugger;
});
}
I expect that my custom activity bar and necessary file will be open after running select. Now file is opened, but activity bar is switched to explorer.
Have no idea, how exactly the problem was solved, but now it works as it should be.
I can assume, that the key here is another plugin (let's call it plugin_2, and main - plugin_1). I have another plugin (plugin_2), which runs when some file opens and draw some result into outline, so probably, when I relocate plugin_2 into my custom activity bar from explorer, and open a file with main plugin_1, plugin_2 ran and didn't let explorer open.
I believe that is the decision. Hope it will help someone.

Popup to Parent Window Communication in Internet Explorer

I have an iframe embedded into a legacy application. Inside of the iframe I need to do oauth (I'm capturing authentication tokens for later use). In order to do oauth from within an iframe I need to use a popup window. What I need is for that popup window to communicate back to the iframe when oauth completes so the page within the iframe can refresh its data. I need to support IE 10+, Chrome, and Firefox, and everything I've tried works fine in Chrome/Firefox but fails in IE. My current solution (which almost works) looks like this:
/** From within the iframe **/
var storageName = 'SoProOauth';
var addAccountDeferred;
$window.addEventListener('storage', function (evt) {
if (evt.key == storageName) {
localStorage.removeItem(storageName);
getAccounts().then(function () {
addAccountDeferred.resolve();
});
}
});
// ... later ...
addAccount: function (type) {
addAccountDeferred = $q.defer();
var uri = util.format('/oauth/%s/connect?auth=%s&return_uri=%s',
type, configuration.get('auth'), encodeURI('/configure/oauthcomplete'));
if (Boolean(configuration.get('debug'))) {
uri += '&debug=true';
}
localStorage.removeItem(storageName);
var oauthWindow = $window.open(uri, 'oauth', 'width=800,height=600');
if (oauthWindow && oauthWindow.focus) oauthWindow.focus();
return addAccountDeferred.promise;
}
/** From within the popup **/
localStorage.setItem('SoProOauth', 'done');
$timeout(function () {
setInfo('This window can be closed');
$window.open('', '_self', '');
$window.close();
}, 500);
Basically, I'm writing to local storage from within the popup window, and listening for the write event in the parent window. This almost works - it works great in my local test environment but fails when I deploy it to the dev cluster. There could be two reasons why it fails: 1) when I run locally everything is over HTTP, but in the dev cluster it is over HTTPS (worse, the page that hosts the iframe is HTTP but the iframe contents are HTTPS), or 2) when I run locally everything is localhost, but in the dev cluster the iframe host is one machine (local intranet) and the contents of the iframe are public internet (AWS).
Other things I've tried: cookies (same result - works locally but fails deployed), and all of the window properties (window.opener, window.parent, and testing for window.closed() from within the iframe) - these don't work in IE as things get reset once the domain changes (which happens because we're doing oauth).
As you can see the UI code is AngularJS, but what you can't see is it is hosted by Node.js. So I've considered using something like socket.io but it seems so heavy-hitting - I really just need to send a quick event from the popup to the parent within the iframe. Any thoughts?

Checking if user has a certain extension installed

I just found out that the Screen Capture by Google extension makes my website's window.onresize event not fire.
I want to perform a javascript check to see if the user has ScreenCapture installed and if so, warn the user of the problem.
A year ago I think I heard of some javascript code that could do this, maybe using some google API, but I don't remember.
Any insight on this? I haven't developed any extensions so I don't really know how they work.
[EDIT]
So I have been asked to show some code. As seen in my previous question ( window.onresize not firing in Chrome but firing in Chrome Incognito ), the problem occurs on any window.onresize event function, so I don't think my code really matters.
Also, there is quite a lot of my code, I don't know how much of it to paste or if it would be helpful.
var debounce = function (func, threshold, execAsap)
{
var timeout;
return function debounced () {//alert("1.1 Y U NO WORK?");
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
}
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
};
window.onresize = debounce(function (e) { //alert("1.2 Y U NO WORK?");
flag = true;
var point = window.center({width:1,height:1});
doCenter(point);
// does something here, but only once after mouse cursor stops
}, 100, false);
I would like to stress that the problem is not due to the debounce. window.onresize = t; function t (e) { alert("wtf?");} won't work either.
[EDIT2]
Here's the result:
var screenCapture = null;
var screenCaptureImg = document.createElement("img");
screenCaptureImg.setAttribute("src", "chrome-extension://cpngackimfmofbokmjmljamhdncknpmg/images/arrow.png");
/*
* Add event listeners for both "load"- and "error"-event
* Set the variable showing the existence of the extension by
* setting it to "true" or "false" according to the fired event
*/
screenCaptureImg.addEventListener("load", doLoad, false);
function doLoad(e){
screenCapture = true; //removeImgTag(e);
alert("I've so cleverly detected that your Chrome has the ScreenCapture extension enabled. \n\nThis extension interferes with my website's DOM and long story short, it won't be able to scale properly.\n\nSo please disable it. \nConsider this extension: \"Disable All Extensions Plus\", it's a handy selective disabler.");
}
screenCaptureImg.addEventListener("error", function(e){
screenCapture = false; //removeImgTag(e);
}, false);
/*
function removeImgTag(e) {
e.currentTarget.parentNode.removeChild(e.currentTarget);
}
*/
Note that I couldn't get removeImgTag to work, because (at least in chrome), I don't seem to have access to the document object in order to create or remove elements from my page, from within these event functions. This is also why I'm displaying an alert instead of elegantly writing up a document.getElementById("something").innerHTML=...
To detect if an extension is installed in Chrome, you can check for a known resource included in the extension such as an image. Resources for the extension are referenced using the following URL pattern:
chrome-extension://<extensionID>/<pathToFile>
The basic detection technique involves creating a hidden image tag and attaching load and error events to it to see if the image loads (as described here for Firefox):
extensionImg.setAttribute("src", "chrome-extension://<INSERT EXTENSION ID HERE>/images/someImage.png"); // See below for discussion of how to find this
/*
* Add event listeners for both "load"- and "error"-event
* Set the variable showing the existence of the extension by
* setting it to "true" or "false" according to the fired event
*/
extensionImg.addEventListener("load", function(e) {
extensionExists = true;
removeImgTag(e);
}, false);
extensionImg.addEventListener("error", function(e) {
extensionExists = false;
removeImgTag(e);
}, false);
function removeImgTag(e) {
e.currentTarget.parentNode.removeChild(e.currentTarget);
}
Check the installation directory of the extension in the Chrome configuration to find a likely target for detection. On my Linux workstation extensions are located in:
~/.config/chromium/Default/Extensions
You can see that I have 3 extensions installed right now:
~/.config/chromium/Default/Extensions$ ls
cpecbmjeidppdiampimghndkikcmoadk nmpeeekfhbmikbdhlpjbfmnpgcbeggic
cpngackimfmofbokmjmljamhdncknpmg
The odd looking names are the unique IDs given to the extension when it is uploaded to the Chrome webstore. You can obtain the ID either from the webstore or by going to the Extensions tab (wrench -> Extensions) and hovering over the link to the extension in question, or "Screen Capture (by Google)" in this case (note the asterisked extension ID):
https://chrome.google.com/webstore/detail/**cpngackimfmofbokmjmljamhdncknpmg**
In the extension directory there will be one or more versions; you can ignore this. Within the version directory is the actual content of the extension:
~/.config/chromium/Default/Extensions/cpngackimfmofbokmjmljamhdncknpmg/5.0.3_0$ ls
account.js images page.js sina_microblog.js
ajax.js isLoad.js picasa.js site.js
background.html _locales plugin style.css
editor.js manifest.json popup.html ui.js
facebook.js notification.html sha1.js upload_ui.js
hotkey_storage.js oauth.js shortcut.js
hub.html options.html showimage.css
i18n_styles page_context.js showimage.html
In the case of the Screen Capture extension there are a number of images to use:
~/.config/chromium/Default/Extensions/cpngackimfmofbokmjmljamhdncknpmg/5.0.3_0/images$ ls
arrow.png icon_128.png icon_save.png print.png
copy.png icon_16.png line.png region.png
cross.png icon_19.png loading.gif screen.png
custom.png icon_32.png loading_icon.gif sina_icon.png
delete_account_icon.png icon_48.png mark.png toolbar_bg.png
down_arrow.png icon_close.png picasa_icon.png upload.png
facebook_icon.png icon_copy.png popup_bg.jpg whole.png
These can be referenced under this URL:
chrome-extension://cpngackimfmofbokmjmljamhdncknpmg/images/arrow.png
This technique obviously depends on the stability of the content of the extension. I recommend using an image that looks likely to remain through all versions.
As mentioned above, the same technique can be used to detect Firefox extensions. In this case the content URL looks like this:
chrome://<EXTENSION NAME>/content/<PATH TO RESOURCE>
On my Linux workstation Firefox extensions are located in:
~/.mozilla/firefox/<USER PROFILE ID>/extensions
Where <USER PROFILE ID> looks something like this: "h4aqaewq.default"
You can see that I have 2 extensions installed right now, one of which is a directory installation and the other of which is a XPI (pronounced "zippy") file:
~/.mozilla/firefox/h4aqaewq.default/extensions$ ls
{3e9a3920-1b27-11da-8cd6-0800200c9a66} staged
firebug#software.joehewitt.com.xpi
The "staged" directory is where Firefox keeps extensions that will be updated (I think). The GUID directory with the brackets is a directory-based extension installation, and the .xpi file is Firebug.
Note: XPI is going away (see the link above). It's basically a zip file that can be opened and inspected by anything that understands zip. I used Emacs.
Finding the extension ID in Firefox is a bit more involved. Go to "Tools -> Add-ons", click the Extensions tab, click the "More" link next to the extension description, then click the "reviews" link to go to the Firefox extension site and get the ID from the URL (note the asterisked extension ID):
https://addons.mozilla.org/en-US/firefox/addon/**firebug**/reviews/?src=api
There's probably an easier way to do this; suggestions welcome.
TODO: how to find a likely image in a Firefox extension.
As an extra note, in Chrome you can only communicate with an extension via the shared DOM of the page: Host page communication

Firebug : How to make net tab persistent?

If I load new web page, the content of the old web page in net tab would all disappear.
Is there a way to make it persistent over different web page?
PS: I'm using Firebug 1.5.4.
Thanks in advance.
According to Jan Odvarko:
It's because of the following code in
tabWatcher.js
// xxxHonza, xxxJJB: web application detection. Based on domain check.
var prevDomain = persistedState ? getDomain(persistedState.location) :
null;
var domain = getDomain(location);
if (!persistedState || prevDomain != domain)
persistedState = null;
If following is commented out, it works.
//if (!persistedState || prevDomain != domain)
// persistedState = null;
Just as a note, If you are using Windows 7, the firebug extension directory path should be somethings like 'C:\Users\Jichao\AppData\Roaming\Mozilla\Firefox\Profiles\2dlypp9o.default\extensions\firebug#software.joehewitt.com\content\firebug'.
As much as I wish this was possible, I don't think it is. Even if you clear the activation list of everything except for 1 web page, when you change tabs Firebug disappears. Even if you have it open in a separate window, it blanks out and gives you an "Activate" button.
Firebug 1.7.a3+ supports this out of the box.
It is still in alpha stage, but it is available for install:
http://getfirebug.com/downloads

Categories

Resources