From 290b9b4bb6cf583205f57280f782451c3a0e690c Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Fri, 4 Dec 2020 16:22:29 +0100 Subject: [PATCH] [TASK] Remove browser-native Notification API TYPO3 has native Browser Notification API since a few TYPO3 versions. However, also due to recent security implementations (permission API) in browsers, and TYPO3 not strongly using this feature (only for LoginRefresh when a login is about to expire, and ONLY when this window is not focussed), this feature is dropped in favor of UX. Resolves: #92988 Releases: master Change-Id: I8e92d96bb47bf060f35b06375d8ff49ff131c185 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/66997 Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Georg Ringer <georg.ringer@gmail.com> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Georg Ringer <georg.ringer@gmail.com> --- .../Public/TypeScript/LoginRefresh.ts | 59 +------------------ .../Public/JavaScript/LoginRefresh.js | 2 +- 2 files changed, 4 insertions(+), 57 deletions(-) diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/LoginRefresh.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/LoginRefresh.ts index 6e967f16bb69..b943fc6ae34e 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/LoginRefresh.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/LoginRefresh.ts @@ -13,11 +13,8 @@ import $ from 'jquery'; import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse'; -import Modal = require('TYPO3/CMS/Backend/Modal'); -import Typo3Notification = require('TYPO3/CMS/Backend/Notification'); -import Severity = require('TYPO3/CMS/Backend/Severity'); -import Client = require('TYPO3/CMS/Backend/Storage/Client'); import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest'); +import Notification = require('TYPO3/CMS/Backend/Notification'); enum MarkupIdentifiers { loginrefresh = 't3js-modal-loginrefresh', @@ -25,9 +22,6 @@ enum MarkupIdentifiers { loginFormModal = 't3js-modal-backendloginform', } -// hack is required, because the Notification definition is wrong -declare let Notification: any; - /** * Module: TYPO3/CMS/Backend/LoginRefresh * @exports TYPO3/CMS/Backend/LoginRefresh @@ -38,7 +32,6 @@ class LoginRefresh { backdrop: 'static', }, }; - private webNotification: Notification = null; private intervalTime: number = 60; private intervalId: number = null; private backendIsLocked: boolean = false; @@ -56,38 +49,7 @@ class LoginRefresh { this.initializeTimeoutModal(); this.initializeBackendLockedModal(); this.initializeLoginForm(); - this.startTask(); - - const askForNotifications = !(Client.isset('notifications.asked') && Client.get('notifications.asked') === 'yes'); - const isDefaultNotificationLevel = typeof Notification !== 'undefined' && Notification.permission === 'default'; - if (askForNotifications - && document.location.protocol === 'https:' - && isDefaultNotificationLevel - ) { - Modal.confirm( - TYPO3.lang['notification.request.title'], - TYPO3.lang['notification.request.description'], - Severity.info, - [{ - text: TYPO3.lang['button.yes'] || 'Yes', - btnClass: 'btn-' + Severity.getCssClass(Severity.info), - name: 'ok', - active: true, - }, { - text: TYPO3.lang['button.no'] || 'No', - btnClass: 'btn-' + Severity.getCssClass(Severity.notice), - name: 'cancel' - }], - ).on('confirm.button.ok', (): void => { - Notification.requestPermission(); - Modal.dismiss(); - }).on('confirm.button.cancel', (): void => { - Modal.dismiss(); - }).on('hide.bs.modal', (): void => { - Client.set('notifications.asked', 'yes'); - }); - } } /** @@ -144,17 +106,6 @@ class LoginRefresh { this.isTimingOut = true; this.$timeoutModal.modal(this.options.modalConfig); this.fillProgressbar(this.$timeoutModal); - - if (document.location.protocol === 'https:' && typeof Notification !== 'undefined' - && Notification.permission === 'granted' && document.hidden) { - this.webNotification = new Notification(TYPO3.lang['mess.login_about_to_expire_title'], { - body: TYPO3.lang['mess.login_about_to_expire'], - icon: '/typo3/sysext/backend/Resources/Public/Images/Logo.png', - }); - this.webNotification.onclick = () => { - window.focus(); - }; - } } /** @@ -163,10 +114,6 @@ class LoginRefresh { public hideTimeoutModal(): void { this.isTimingOut = false; this.$timeoutModal.modal('hide'); - - if (typeof Notification !== 'undefined' && this.webNotification !== null) { - this.webNotification.close(); - } } /** @@ -399,7 +346,7 @@ class LoginRefresh { const passwordFieldValue = $passwordField.val(); if (passwordFieldValue === '' && $useridentField.val() === '') { - Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_emptyPassword']); + Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_emptyPassword']); $passwordField.focus(); return; } @@ -421,7 +368,7 @@ class LoginRefresh { // User is logged in this.hideLoginForm(); } else { - Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_failed_message']); + Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_failed_message']); $passwordField.focus(); } }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js b/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js index 73e1c015dd13..79bb6038e929 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Backend/Modal","TYPO3/CMS/Backend/Notification","TYPO3/CMS/Backend/Severity","TYPO3/CMS/Backend/Storage/Client","TYPO3/CMS/Core/Ajax/AjaxRequest"],(function(e,t,o,i,s,n,a,l){"use strict";var d;o=__importDefault(o),function(e){e.loginrefresh="t3js-modal-loginrefresh",e.lockedModal="t3js-modal-backendlocked",e.loginFormModal="t3js-modal-backendloginform"}(d||(d={}));class r{constructor(){this.options={modalConfig:{backdrop:"static"}},this.webNotification=null,this.intervalTime=60,this.intervalId=null,this.backendIsLocked=!1,this.isTimingOut=!1,this.$timeoutModal=null,this.$backendLockedModal=null,this.$loginForm=null,this.loginFramesetUrl="",this.logoutUrl="",this.submitForm=e=>{e.preventDefault();const t=this.$loginForm.find("form"),i=t.find("input[name=p_field]"),n=t.find("input[name=userident]"),a=i.val();if(""===a&&""===n.val())return s.error(TYPO3.lang["mess.refresh_login_failed"],TYPO3.lang["mess.refresh_login_emptyPassword"]),void i.focus();a&&(n.val(a),i.val(""));const d={login_status:"login"};o.default.each(t.serializeArray(),(function(e,t){d[t.name]=t.value})),new l(t.attr("action")).post(d).then(async e=>{(await e.resolve()).login.success?this.hideLoginForm():(s.error(TYPO3.lang["mess.refresh_login_failed"],TYPO3.lang["mess.refresh_login_failed_message"]),i.focus())})},this.checkActiveSession=()=>{new l(TYPO3.settings.ajaxUrls.login_timedout).get().then(async e=>{const t=await e.resolve();t.login.locked?this.backendIsLocked||(this.backendIsLocked=!0,this.showBackendLockedModal()):this.backendIsLocked&&(this.backendIsLocked=!1,this.hideBackendLockedModal()),this.backendIsLocked||(t.login.timed_out||t.login.will_time_out)&&(t.login.timed_out?this.showLoginForm():this.showTimeoutModal())})}}initialize(){this.initializeTimeoutModal(),this.initializeBackendLockedModal(),this.initializeLoginForm(),this.startTask();const e=!(a.isset("notifications.asked")&&"yes"===a.get("notifications.asked")),t="undefined"!=typeof Notification&&"default"===Notification.permission;e&&"https:"===document.location.protocol&&t&&i.confirm(TYPO3.lang["notification.request.title"],TYPO3.lang["notification.request.description"],n.info,[{text:TYPO3.lang["button.yes"]||"Yes",btnClass:"btn-"+n.getCssClass(n.info),name:"ok",active:!0},{text:TYPO3.lang["button.no"]||"No",btnClass:"btn-"+n.getCssClass(n.notice),name:"cancel"}]).on("confirm.button.ok",()=>{Notification.requestPermission(),i.dismiss()}).on("confirm.button.cancel",()=>{i.dismiss()}).on("hide.bs.modal",()=>{a.set("notifications.asked","yes")})}startTask(){if(null!==this.intervalId)return;let e=1e3*this.intervalTime;this.intervalId=setInterval(this.checkActiveSession,e)}stopTask(){clearInterval(this.intervalId),this.intervalId=null}setIntervalTime(e){this.intervalTime=Math.min(e,86400)}setLogoutUrl(e){this.logoutUrl=e}setLoginFramesetUrl(e){this.loginFramesetUrl=e}showTimeoutModal(){this.isTimingOut=!0,this.$timeoutModal.modal(this.options.modalConfig),this.fillProgressbar(this.$timeoutModal),"https:"===document.location.protocol&&"undefined"!=typeof Notification&&"granted"===Notification.permission&&document.hidden&&(this.webNotification=new Notification(TYPO3.lang["mess.login_about_to_expire_title"],{body:TYPO3.lang["mess.login_about_to_expire"],icon:"/typo3/sysext/backend/Resources/Public/Images/Logo.png"}),this.webNotification.onclick=()=>{window.focus()})}hideTimeoutModal(){this.isTimingOut=!1,this.$timeoutModal.modal("hide"),"undefined"!=typeof Notification&&null!==this.webNotification&&this.webNotification.close()}showBackendLockedModal(){this.$backendLockedModal.modal(this.options.modalConfig)}hideBackendLockedModal(){this.$backendLockedModal.modal("hide")}showLoginForm(){new l(TYPO3.settings.ajaxUrls.logout).get().then(()=>{TYPO3.configuration.showRefreshLoginPopup?this.showLoginPopup():this.$loginForm.modal(this.options.modalConfig)})}showLoginPopup(){const e=window.open(this.loginFramesetUrl,"relogin_"+Math.random().toString(16).slice(2),"height=450,width=700,status=0,menubar=0,location=1");e&&e.focus()}hideLoginForm(){this.$loginForm.modal("hide")}initializeBackendLockedModal(){this.$backendLockedModal=this.generateModal(d.lockedModal),this.$backendLockedModal.find(".modal-header h4").text(TYPO3.lang["mess.please_wait"]),this.$backendLockedModal.find(".modal-body").append(o.default("<p />").text(TYPO3.lang["mess.be_locked"])),this.$backendLockedModal.find(".modal-footer").remove(),o.default("body").append(this.$backendLockedModal)}initializeTimeoutModal(){this.$timeoutModal=this.generateModal(d.loginrefresh),this.$timeoutModal.addClass("modal-severity-notice"),this.$timeoutModal.find(".modal-header h4").text(TYPO3.lang["mess.login_about_to_expire_title"]),this.$timeoutModal.find(".modal-body").append(o.default("<p />").text(TYPO3.lang["mess.login_about_to_expire"]),o.default("<div />",{class:"progress"}).append(o.default("<div />",{class:"progress-bar progress-bar-warning progress-bar-striped active",role:"progressbar","aria-valuemin":"0","aria-valuemax":"100"}).append(o.default("<span />",{class:"sr-only"})))),this.$timeoutModal.find(".modal-footer").append(o.default("<button />",{class:"btn btn-default","data-action":"logout"}).text(TYPO3.lang["mess.refresh_login_logout_button"]).on("click",()=>{top.location.href=this.logoutUrl}),o.default("<button />",{class:"btn btn-primary t3js-active","data-action":"refreshSession"}).text(TYPO3.lang["mess.refresh_login_refresh_button"]).on("click",()=>{new l(TYPO3.settings.ajaxUrls.login_timedout).get().then(()=>{this.hideTimeoutModal()})})),this.registerDefaultModalEvents(this.$timeoutModal),o.default("body").append(this.$timeoutModal)}initializeLoginForm(){if(TYPO3.configuration.showRefreshLoginPopup)return;this.$loginForm=this.generateModal(d.loginFormModal),this.$loginForm.addClass("modal-notice");let t=String(TYPO3.lang["mess.refresh_login_title"]).replace("%s",TYPO3.configuration.username);this.$loginForm.find(".modal-header h4").text(t),this.$loginForm.find(".modal-body").append(o.default("<p />").text(TYPO3.lang["mess.login_expired"]),o.default("<form />",{id:"beLoginRefresh",method:"POST",action:TYPO3.settings.ajaxUrls.login}).append(o.default("<div />",{class:"form-group"}).append(o.default("<input />",{type:"password",name:"p_field",autofocus:"autofocus",class:"form-control",placeholder:TYPO3.lang["mess.refresh_login_password"],"data-rsa-encryption":"t3-loginrefres-userident"})),o.default("<input />",{type:"hidden",name:"username",value:TYPO3.configuration.username}),o.default("<input />",{type:"hidden",name:"userident",id:"t3-loginrefres-userident"}))),this.$loginForm.find(".modal-footer").append(o.default("<a />",{href:this.logoutUrl,class:"btn btn-default"}).text(TYPO3.lang["mess.refresh_exit_button"]),o.default("<button />",{type:"button",class:"btn btn-primary","data-action":"refreshSession"}).text(TYPO3.lang["mess.refresh_login_button"]).on("click",()=>{this.$loginForm.find("form").trigger("submit")})),this.registerDefaultModalEvents(this.$loginForm).on("submit",this.submitForm),o.default("body").append(this.$loginForm),e.specified("TYPO3/CMS/Rsaauth/RsaEncryptionModule")&&e(["TYPO3/CMS/Rsaauth/RsaEncryptionModule"],(function(e){e.registerForm(o.default("#beLoginRefresh").get(0))}))}generateModal(e){return o.default("<div />",{id:e,class:"t3js-modal "+e+" modal modal-type-default modal-severity-notice modal-style-light modal-size-small fade"}).append(o.default("<div />",{class:"modal-dialog"}).append(o.default("<div />",{class:"modal-content"}).append(o.default("<div />",{class:"modal-header"}).append(o.default("<h4 />",{class:"modal-title"})),o.default("<div />",{class:"modal-body"}),o.default("<div />",{class:"modal-footer"}))))}fillProgressbar(e){if(!this.isTimingOut)return;let t=0;const o=e.find(".progress-bar"),i=o.children(".sr-only"),s=setInterval(()=>{const e=t>=100;!this.isTimingOut||e?(clearInterval(s),e&&(this.hideTimeoutModal(),this.showLoginForm()),t=0):t+=1;const n=t+"%";o.css("width",n),i.text(n)},300)}registerDefaultModalEvents(e){return e.on("hidden.bs.modal",()=>{this.startTask()}).on("shown.bs.modal",()=>{this.stopTask(),this.$timeoutModal.find(".modal-footer .t3js-active").first().focus()}),e}}let c;try{window.opener&&window.opener.TYPO3&&window.opener.TYPO3.LoginRefresh&&(c=window.opener.TYPO3.LoginRefresh),parent&&parent.window.TYPO3&&parent.window.TYPO3.LoginRefresh&&(c=parent.window.TYPO3.LoginRefresh),top&&top.TYPO3&&top.TYPO3.LoginRefresh&&(c=top.TYPO3.LoginRefresh)}catch(e){}return c||(c=new r,"undefined"!=typeof TYPO3&&(TYPO3.LoginRefresh=c)),c})); \ No newline at end of file +var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest","TYPO3/CMS/Backend/Notification"],(function(e,t,o,i,s){"use strict";var a;o=__importDefault(o),function(e){e.loginrefresh="t3js-modal-loginrefresh",e.lockedModal="t3js-modal-backendlocked",e.loginFormModal="t3js-modal-backendloginform"}(a||(a={}));class n{constructor(){this.options={modalConfig:{backdrop:"static"}},this.intervalTime=60,this.intervalId=null,this.backendIsLocked=!1,this.isTimingOut=!1,this.$timeoutModal=null,this.$backendLockedModal=null,this.$loginForm=null,this.loginFramesetUrl="",this.logoutUrl="",this.submitForm=e=>{e.preventDefault();const t=this.$loginForm.find("form"),a=t.find("input[name=p_field]"),n=t.find("input[name=userident]"),l=a.val();if(""===l&&""===n.val())return s.error(TYPO3.lang["mess.refresh_login_failed"],TYPO3.lang["mess.refresh_login_emptyPassword"]),void a.focus();l&&(n.val(l),a.val(""));const d={login_status:"login"};o.default.each(t.serializeArray(),(function(e,t){d[t.name]=t.value})),new i(t.attr("action")).post(d).then(async e=>{(await e.resolve()).login.success?this.hideLoginForm():(s.error(TYPO3.lang["mess.refresh_login_failed"],TYPO3.lang["mess.refresh_login_failed_message"]),a.focus())})},this.checkActiveSession=()=>{new i(TYPO3.settings.ajaxUrls.login_timedout).get().then(async e=>{const t=await e.resolve();t.login.locked?this.backendIsLocked||(this.backendIsLocked=!0,this.showBackendLockedModal()):this.backendIsLocked&&(this.backendIsLocked=!1,this.hideBackendLockedModal()),this.backendIsLocked||(t.login.timed_out||t.login.will_time_out)&&(t.login.timed_out?this.showLoginForm():this.showTimeoutModal())})}}initialize(){this.initializeTimeoutModal(),this.initializeBackendLockedModal(),this.initializeLoginForm(),this.startTask()}startTask(){if(null!==this.intervalId)return;let e=1e3*this.intervalTime;this.intervalId=setInterval(this.checkActiveSession,e)}stopTask(){clearInterval(this.intervalId),this.intervalId=null}setIntervalTime(e){this.intervalTime=Math.min(e,86400)}setLogoutUrl(e){this.logoutUrl=e}setLoginFramesetUrl(e){this.loginFramesetUrl=e}showTimeoutModal(){this.isTimingOut=!0,this.$timeoutModal.modal(this.options.modalConfig),this.fillProgressbar(this.$timeoutModal)}hideTimeoutModal(){this.isTimingOut=!1,this.$timeoutModal.modal("hide")}showBackendLockedModal(){this.$backendLockedModal.modal(this.options.modalConfig)}hideBackendLockedModal(){this.$backendLockedModal.modal("hide")}showLoginForm(){new i(TYPO3.settings.ajaxUrls.logout).get().then(()=>{TYPO3.configuration.showRefreshLoginPopup?this.showLoginPopup():this.$loginForm.modal(this.options.modalConfig)})}showLoginPopup(){const e=window.open(this.loginFramesetUrl,"relogin_"+Math.random().toString(16).slice(2),"height=450,width=700,status=0,menubar=0,location=1");e&&e.focus()}hideLoginForm(){this.$loginForm.modal("hide")}initializeBackendLockedModal(){this.$backendLockedModal=this.generateModal(a.lockedModal),this.$backendLockedModal.find(".modal-header h4").text(TYPO3.lang["mess.please_wait"]),this.$backendLockedModal.find(".modal-body").append(o.default("<p />").text(TYPO3.lang["mess.be_locked"])),this.$backendLockedModal.find(".modal-footer").remove(),o.default("body").append(this.$backendLockedModal)}initializeTimeoutModal(){this.$timeoutModal=this.generateModal(a.loginrefresh),this.$timeoutModal.addClass("modal-severity-notice"),this.$timeoutModal.find(".modal-header h4").text(TYPO3.lang["mess.login_about_to_expire_title"]),this.$timeoutModal.find(".modal-body").append(o.default("<p />").text(TYPO3.lang["mess.login_about_to_expire"]),o.default("<div />",{class:"progress"}).append(o.default("<div />",{class:"progress-bar progress-bar-warning progress-bar-striped active",role:"progressbar","aria-valuemin":"0","aria-valuemax":"100"}).append(o.default("<span />",{class:"sr-only"})))),this.$timeoutModal.find(".modal-footer").append(o.default("<button />",{class:"btn btn-default","data-action":"logout"}).text(TYPO3.lang["mess.refresh_login_logout_button"]).on("click",()=>{top.location.href=this.logoutUrl}),o.default("<button />",{class:"btn btn-primary t3js-active","data-action":"refreshSession"}).text(TYPO3.lang["mess.refresh_login_refresh_button"]).on("click",()=>{new i(TYPO3.settings.ajaxUrls.login_timedout).get().then(()=>{this.hideTimeoutModal()})})),this.registerDefaultModalEvents(this.$timeoutModal),o.default("body").append(this.$timeoutModal)}initializeLoginForm(){if(TYPO3.configuration.showRefreshLoginPopup)return;this.$loginForm=this.generateModal(a.loginFormModal),this.$loginForm.addClass("modal-notice");let t=String(TYPO3.lang["mess.refresh_login_title"]).replace("%s",TYPO3.configuration.username);this.$loginForm.find(".modal-header h4").text(t),this.$loginForm.find(".modal-body").append(o.default("<p />").text(TYPO3.lang["mess.login_expired"]),o.default("<form />",{id:"beLoginRefresh",method:"POST",action:TYPO3.settings.ajaxUrls.login}).append(o.default("<div />",{class:"form-group"}).append(o.default("<input />",{type:"password",name:"p_field",autofocus:"autofocus",class:"form-control",placeholder:TYPO3.lang["mess.refresh_login_password"],"data-rsa-encryption":"t3-loginrefres-userident"})),o.default("<input />",{type:"hidden",name:"username",value:TYPO3.configuration.username}),o.default("<input />",{type:"hidden",name:"userident",id:"t3-loginrefres-userident"}))),this.$loginForm.find(".modal-footer").append(o.default("<a />",{href:this.logoutUrl,class:"btn btn-default"}).text(TYPO3.lang["mess.refresh_exit_button"]),o.default("<button />",{type:"button",class:"btn btn-primary","data-action":"refreshSession"}).text(TYPO3.lang["mess.refresh_login_button"]).on("click",()=>{this.$loginForm.find("form").trigger("submit")})),this.registerDefaultModalEvents(this.$loginForm).on("submit",this.submitForm),o.default("body").append(this.$loginForm),e.specified("TYPO3/CMS/Rsaauth/RsaEncryptionModule")&&e(["TYPO3/CMS/Rsaauth/RsaEncryptionModule"],(function(e){e.registerForm(o.default("#beLoginRefresh").get(0))}))}generateModal(e){return o.default("<div />",{id:e,class:"t3js-modal "+e+" modal modal-type-default modal-severity-notice modal-style-light modal-size-small fade"}).append(o.default("<div />",{class:"modal-dialog"}).append(o.default("<div />",{class:"modal-content"}).append(o.default("<div />",{class:"modal-header"}).append(o.default("<h4 />",{class:"modal-title"})),o.default("<div />",{class:"modal-body"}),o.default("<div />",{class:"modal-footer"}))))}fillProgressbar(e){if(!this.isTimingOut)return;let t=0;const o=e.find(".progress-bar"),i=o.children(".sr-only"),s=setInterval(()=>{const e=t>=100;!this.isTimingOut||e?(clearInterval(s),e&&(this.hideTimeoutModal(),this.showLoginForm()),t=0):t+=1;const a=t+"%";o.css("width",a),i.text(a)},300)}registerDefaultModalEvents(e){return e.on("hidden.bs.modal",()=>{this.startTask()}).on("shown.bs.modal",()=>{this.stopTask(),this.$timeoutModal.find(".modal-footer .t3js-active").first().focus()}),e}}let l;try{window.opener&&window.opener.TYPO3&&window.opener.TYPO3.LoginRefresh&&(l=window.opener.TYPO3.LoginRefresh),parent&&parent.window.TYPO3&&parent.window.TYPO3.LoginRefresh&&(l=parent.window.TYPO3.LoginRefresh),top&&top.TYPO3&&top.TYPO3.LoginRefresh&&(l=top.TYPO3.LoginRefresh)}catch(e){}return l||(l=new n,"undefined"!=typeof TYPO3&&(TYPO3.LoginRefresh=l)),l})); \ No newline at end of file -- GitLab