From 27226145f7ac0c5acf7aa13e6c8b26687b4e1013 Mon Sep 17 00:00:00 2001 From: TheGoddessInari Date: Fri, 12 Nov 2021 19:21:30 -0800 Subject: [PATCH] Fix popups/link opening in general. Fixes #280. Fixes #255. Fixes #232. Fixes #220. Fixes #121. Co-authored-by: Ramiro Saenz Reference https://github.com/ramboxapp/community-edition/commit/c91ef575e3ccdc8391335bb6c473dd4f286f29b5 --- app/ux/WebView.js | 155 ++++------------------------------------------ electron/main.js | 116 ++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 144 deletions(-) diff --git a/app/ux/WebView.js b/app/ux/WebView.js index 971ff86f..09c4a6dc 100644 --- a/app/ux/WebView.js +++ b/app/ux/WebView.js @@ -147,15 +147,12 @@ Ext.define('Hamsket.ux.WebView',{ let cfg; enabled = enabled || me.record.get('enabled'); - if ( !enabled ) { - cfg = [{ + cfg = !enabled ? [{ xtype: 'container' ,html: '

Service Disabled

' ,style: 'text-align:center;' ,padding: 100 - }]; - } else { - cfg = [{ + }] : [{ xtype: 'component' ,hideMode: 'offsets' ,autoRender: true @@ -167,16 +164,14 @@ Ext.define('Hamsket.ux.WebView',{ ,partition: 'persist:' + me.record.get('type') + '_' + me.id.replace('tab_', '') ,allowtransparency: 'on' ,autosize: 'on' - ,webpreferences: 'enableRemoteModule=yes,spellcheck=yes,contextIsolation=no' //,nativeWindowOpen=true + ,webpreferences: 'nativeWindowOpen=yes,enableRemoteModule=yes,spellcheck=yes,contextIsolation=no' //,nativeWindowOpen=true + ,allowpopups: 'on' //,disablewebsecurity: 'on' // Disabled because some services (Like Google Drive) dont work with this enabled ,userAgent: me.getUserAgent() ,preload: './resources/js/hamsket-service-api.js' } }]; - if ( Ext.getStore('ServicesList').getById(me.record.get('type')).get('allow_popups') ) cfg[0].autoEl.allowpopups = 'on'; - } - return cfg; } @@ -262,141 +257,13 @@ Ext.define('Hamsket.ux.WebView',{ }); // Open links in default browser - webview.addEventListener('new-window', function(e) { - switch ( me.type ) { - case 'skype': - // hack to fix multiple browser tabs on Skype link click, re #11 - if ( e.url.match(/https:\/\/web.skype.com\/..\/undefined/) ) { - e.preventDefault(); - return; - } else if ( e.url.indexOf('imgpsh_fullsize') >= 0 ) { - ipc.send('image:download', e.url, e.target.partition); - e.preventDefault(); - return; - } - break; - case 'hangouts': - e.preventDefault(); - if ( e.url.indexOf('plus.google.com/u/0/photos/albums') >= 0 ) { - ipc.send('image:popup', e.url, e.target.partition); - return; - } else if ( e.url.indexOf('/el/CONVERSATION/') >= 0 ) { - me.add({ - xtype: 'window' - ,title: 'Video Call' - ,width: '80%' - ,height: '80%' - ,maximizable: true - ,resizable: true - ,draggable: true - ,collapsible: true - ,items: { - xtype: 'component' - ,hideMode: 'offsets' - ,autoRender: true - ,autoShow: true - ,autoEl: { - tag: 'webview' - ,src: e.url - ,style: 'width:100%;height:100%;' - ,partition: me.getWebView().partition - ,useragent: me.getUserAgent() - } - } - }).show(); - return; - } - break; - case 'slack': - if ( e.url.indexOf('slack.com/call/') >= 0 ) { - me.add({ - xtype: 'window' - ,title: Ext.String.htmlEncode(e.options.title) - ,width: e.options.width - ,height: e.options.height - ,maximizable: true - ,resizable: true - ,draggable: true - ,collapsible: true - ,items: { - xtype: 'component' - ,hideMode: 'offsets' - ,autoRender: true - ,autoShow: true - ,autoEl: { - tag: 'webview' - ,src: e.url - ,style: 'width:100%;height:100%;' - ,partition: me.getWebView().partition - ,useragent: me.getUserAgent() - } - } - }).show(); - e.preventDefault(); - return; - } - break; - case 'icloud': - if ( e.url.indexOf('index.html#compose') >= 0 ) { - me.add({ - xtype: 'window' - ,title: 'iCloud - Compose' - ,width: 700 - ,height: 500 - ,maximizable: true - ,resizable: true - ,draggable: true - ,collapsible: true - ,items: { - xtype: 'component' - ,itemId: 'webview' - ,hideMode: 'offsets' - ,autoRender: true - ,autoShow: true - ,autoEl: { - tag: 'webview' - ,src: e.url - ,style: 'width:100%;height:100%;' - ,partition: me.getWebView().partition - ,useragent: me.getUserAgent() - ,preload: './resources/js/hamsket-modal-api.js' - } - } - ,listeners: { - show(win) { - const webview = win.down('#webview').el.dom; - webview.addEventListener('ipc-message', function(event) { - const channel = event.channel; - switch (channel) { - case 'close': - win.close(); - break; - default: - break; - } - }); - } - } - }).show(); - e.preventDefault(); - return; - } - break; - case 'flowdock': - if ( e.disposition === 'new-window' ) { - e.preventDefault(); - require('electron').remote.shell.openExternal(e.url); - } - return; - default: - break; - } - - const protocol = require('url').parse(e.url).protocol; - if (protocol === 'http:' || protocol === 'https:' || protocol === 'mailto:') { - e.preventDefault(); - require('electron').remote.shell.openExternal(e.url); - } + webview.addEventListener('new-window', function (e) { + e.preventDefault(); + const protocol = require('url').URL(e.url).protocol; + // Block some Deep links to prevent that open its app (Ex: Slack) + if (['slack:'].includes(protocol)) return; + // Allow Deep links + if (!['http:', 'https:', 'about:'].includes(protocol)) return require('electron').shell.openExternal(e.url); }); webview.addEventListener('will-navigate', function(e, url) { diff --git a/electron/main.js b/electron/main.js index 075ed4e4..3a8dc23f 100644 --- a/electron/main.js +++ b/electron/main.js @@ -61,6 +61,9 @@ if (config.get('enable_hidpi_support') && (process.platform === 'win32')) { app.commandLine.appendSwitch('force-device-scale-factor', '1'); } +// TODO: https://github.com/electron/electron/issues/25469 +app.commandLine.appendSwitch('disable-features', 'CrossOriginOpenerPolicy'); + // This must match the package name in package.json app.setAppUserModelId('com.thegoddessinari.hamsket'); @@ -357,6 +360,119 @@ if (!haveLock) { app.quit(); } +const allowPopUp = [ + '=?print=true', // esta ultima checkea como anda imprimir un pedf desde gmail, si no va bie sacala + 'accounts.google.com/AccountChooser', + 'accounts.google.com/o/oauth2', + 'api.moo.do', + 'app.mixmax.com/_oauth/google', + 'app.slack.com/files/import/dropbox', + 'app.slack.com/files/import/gdrive', + 'app.slack.com/free-willy/', + 'auth.missiveapp.com', + 'dropbox.com/profile_services/start_auth_flow', + 'facebook.com/v3.1/dialog/oauth?', + 'facebook.com/v3.2/dialog/oauth?', + 'feedly.com/v3/auth/', + 'figma.com/start_google_sso', + 'hangouts.google.com/webchat/u/0/frame', + 'identity.linuxfoundation.org/cas/login', + 'mail.google.com/mail', + 'manychat.com/fb?popup', + 'messenger.com/videocall', + 'notion.so/googlepopupredirect', + 'officeapps.live.com', + 'spikenow.com/s/account', + 'zoom.us/office365', +]; + +app.on('web-contents-created', (webContentsCreatedEvent, contents) => { + if (contents.getType() !== 'webview') return; + // Block some Deep links to prevent that open its app (Ex: Slack) + contents.on( + 'will-navigate', + (event, url) => url.slice(0, 8) === 'slack://' && event.preventDefault() + ); + // New Window handler + contents.on( + 'new-window', + ( + event, + url, + frameName, + disposition, + options, + additionalFeatures, + referrer, + postBody + ) => { + // If the url is about:blank we allow the window and handle it in 'did-create-window' + if (['about:blank', 'about:blank#blocked'].includes(url)) { + event.preventDefault(); + Object.assign(options, { + show: false, + }); + const win = new BrowserWindow(options); + win.center(); + let once = false; + win.webContents.on('will-navigate', (e, nextURL) => { + if (once) return; + if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return; + once = true; + let allow = false; + for (const url of allowPopUp) { + if (nextURL.includes(url)) { + allow = true; + break; + } + } + // If the url is in aboutBlankOnlyWindow we handle this as a popup window + if (allow) return win.show(); + shell.openExternal(nextURL); + win.close(); + }); + event.newGuest = win; + return; + } + // We check if url is in the allowPopUpLoginURLs or allowForegroundTabURLs in Firebase to open a as a popup, + // if it is not we send this to the app + let allow = false; + for (const allowed of allowPopUp) { + if (url.includes(allowed)) { + allow = true; + break; + } + } + if (allow) return; + shell.openExternal(url); + event.preventDefault(); + } + ); + contents.on('did-create-window', (win, details) => { + // Here we center the new window. + win.center(); + // The following code is for handling the about:blank cases only. + if (!['about:blank', 'about:blank#blocked'].includes(details.url)) return; + let once = false; + win.webContents.on('will-navigate', (e, nextURL) => { + if (once) return; + if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return; + once = true; + let allow = false; + for (const url of allowPopUp) { + if (nextURL.includes(url)) { + allow = true; + break; + } + } + // If the url is in aboutBlankOnlyWindow we handle this as a popup window + if (allow) return win.show(); + shell.openExternal(url); + win.close(); + }); + }); +}); + // Code for downloading images as temporal files // Credit: Ghetto Skype (https://github.com/stanfieldr/ghetto-skype) let imageCache = {};