add a function to test if we have a safe opener

This commit is contained in:
Jacob Overgaard
2024-05-24 11:35:30 +02:00
parent c8d3772635
commit a0be30d77b
3 changed files with 100 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ export * from './object/deep-merge.function.js';
export * from './pagination-manager/pagination.manager.js';
export * from './path/ensure-local-path.function.js';
export * from './path/ensure-path-ends-with-slash.function.js';
export * from './path/has-own-opener.function.js';
export * from './path/path-decode.function.js';
export * from './path/path-encode.function.js';
export * from './path/path-folder-name.function.js';

View File

@@ -0,0 +1,64 @@
import { expect } from '@open-wc/testing';
import { hasOwnOpener } from './has-own-opener.function.js';
describe('hasOwnOpener', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let mockWindow: any;
beforeEach(() => {
mockWindow = {
location: {
origin: 'http://localhost',
pathname: '/test',
},
};
});
it('should return false if there is no opener', () => {
expect(hasOwnOpener(undefined, mockWindow)).to.be.false;
});
it('should return false if the opener is from a different origin', () => {
mockWindow.opener = {
location: {
origin: 'https://example.com',
pathname: '/test',
},
};
expect(hasOwnOpener(undefined, mockWindow)).to.be.false;
});
it('should return true if the opener is from the same origin and no pathname is specified', () => {
mockWindow.opener = {
location: {
origin: 'http://localhost',
pathname: '/test',
},
};
expect(hasOwnOpener(undefined, mockWindow)).to.be.true;
});
it('should return false if the opener is from the same origin but has a different pathname', () => {
mockWindow.opener = {
location: {
origin: 'http://localhost',
pathname: '/different',
},
};
expect(hasOwnOpener('/test', mockWindow)).to.be.false;
});
it('should return true if the opener is from the same origin and has the same pathname', () => {
mockWindow.opener = {
location: {
origin: 'http://localhost',
pathname: '/test',
},
};
expect(hasOwnOpener('/test', mockWindow)).to.be.true;
});
});

View File

@@ -0,0 +1,35 @@
/**
* Check if the current window has an opener window with the same origin and optional pathname.
* This is useful for checking if the current window was opened by another window from within the same application.
* @remark If the current window was opened by another window, the opener window is accessible via `window.opener`.
* @remark There could still be an opener if the opener window is closed or navigated away or if the opener window is not from the same origin,
* but this function will only return `true` if the opener window is accessible and has the same origin and optional pathname.
*
* @param pathname Optional pathname to check if the opener window has the same pathname.
* @param windowLike The window-like object to use for checking the opener. Default is `window`.
* @returns `true` if the current window has an opener window with the same origin and optional pathname, otherwise `false`.
*/
export function hasOwnOpener(pathname?: string, windowLike: Window = globalThis.window): boolean {
try {
const opener = windowLike.opener;
if (!opener) {
return false;
}
const openerLocation = opener.location;
const currentLocation = windowLike.location;
if (openerLocation.origin !== currentLocation.origin) {
return false;
}
if (pathname && openerLocation.pathname !== pathname) {
return false;
}
return true;
} catch (e) {
// If there is a security error, it means that the opener is from a different origin, so we let it fall through
return false;
}
}