I'm using Electron I have a webview which display an external website but I can't succeed to show the additional window normally opened by links on this site and which have target = _blank.
Mentions légales
I tried with
webpreferences="nativeWindowOpen=yes" allowpopups
But it didn't change.
With a webview, you can actually handle these on the main process quite easily.
Which also allows you to disable nodeIntegration should that be a requirement.
// Listen for web contents being created
app.on('web-contents-created', (e, contents) => {
// Check for a webview
if (contents.getType() == 'webview') {
// Listen for any new window events
contents.on('new-window', (e, url) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
After digging into the documentation I wrote this code (code located in the renderer):
const {BrowserWindow} = require('electron').remote
..........
webview1.addEventListener('new-window', (e) => {
const protocol = require('url').parse(e.url).protocol
if (protocol === 'http:' || protocol === 'https:') {
//shell.openExternal(e.url)
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL(e.url);
}
})
The line shell.openExternal(e.url) open the url of the link in a tab of the default browser.
And by using a new BrowserWindow, the new windows are Electron Window.
Related
I've been trying to get deeplinks to work to do oauth for like 4 weeks:
on different boilerplates
on raw quick start of electron
on electron-forge with webpack.
None of them work while in dev mode, and only does while packaged.
I do not understand why it only works if I target command line the electron.exe and pass my app. OR when the app is packaged. If it's in development mode, it simply does not work.
I think? that the gotTheLock runs app.quit(), because in instances where I put the createWindow() outside of the lock if/else function, a window briefly opens and then closes immediately. For some reason it's opening a new instance completely? When createWindow() is inside, I basically see nothing happen.
I'm on Windows, I see nothing about forge that would cause issues or need extra setup in the forge config/package.json since I am on Windows
There's something fundamental flying over my head. Currently, my latest attempt is with the new 6.0 electron-forge from here with the following npm command to generate:
npm init electron-app#latest my-app --template=webpack cd my-app npm start
Here is my "main" which is called index.js here.
index.js
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) {
app.quit();
}
let mainWindow;
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
}
} else {
app.setAsDefaultProtocolClient('electron-fiddle')
}
const createWindow = () => {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
})
app.on('ready', createWindow);
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
ipcMain.on('shell:open', () => {
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
const pagePath = path.join('file://', pageDirectory, 'index.html')
shell.openExternal(pagePath)
})
I've tried so many iterations i'm honestly just lost. What's wrong with this that the electron-forge dev mode doesn't like?
As far as any other code is concerned, it's "as-is" from that npm command with the latest 6.0 electron-forge with webpack template. Only the index.js was modified
I have a deeplinking configuration setup to open a specific page when a URL is clicked on the device. This is working fine when the app is open in the background, but if the app is closed, it just opens the app and does not navigate.
Here is my linking configuration:
const linking = {
prefixes: ["appname://"],
config: deepLinkRouting,
getStateFromPath(path:string, options:any) {
//build custom params
},
async getInitialURL() {
// Check if app was opened from a deep link
const url = await Linking.getInitialURL();
if (url != null) {
return url;
}
},
subscribe(listener) {
const onReceiveURL = ({ url }) => listener(url);
Linking.addEventListener('url', onReceiveURL);
return () => {
// Clean up the event listener
Linking.removeEventListener('url', onReceiveURL);
};
},
}
This linking object is provided as a prop to my <NavigationContainer/>
I am testing this on simulator with the npx uri-scheme open command. I notice when you close the app and reopen it, the app is rebuilt, so I'm wondering if this invalidates testing. Any help is appreciated!
The user story:
On a browser, I have my Progressive Web App opened on any URL
https://mypwa.com/xxxx
I receive a mail, with a link to a page of my PWA
https://mypwa.com/post/<postId>
Instead of opening a new tab in the browser, I want my existing PWA tab to get the focus and go on the URL. I don't want a new tab nor a new PWA startup (it costs a lot in records download)
With postMessage, Service Worker can tell existing tab to get focus and go on the /post/<postId> path. Supposed to work but I get a "DOM Exception" on client.focus() in the service worker, from a fetch event, in short:
self.addEventListener("fetch", function(event) {
var requestUrl = new URL(event.request.url);
var pathname = requestUrl.pathname;
if (
event.request.mode === "navigate" &&
requestUrl.origin === location.origin
) {
const rootUrl = new URL("/", location).href;
const mg = pathname.match(regexpPost);
const postId = mg[1];
event.waitUntil(
clients.matchAll().then(matchedClients => {
for (let client of matchedClients) {
if (client.url.indexOf(rootUrl) >= 0) {
return client
.focus() // ***** CRASHING HERE *****
.then(() => {
return sendMessageClient(client, { postId }).then(resp => {
other;
});
});
}
}
})
);
}
});
What I'm missing also is how to close the newly opened tab. I don't want to keep it: dead tabs can accumulate and this is not a good user experience.
Tried javascript window.close(); but it has to respond to a user action...
I'm attempting to open a window from an electron app. Trying to have this opened window node-integration set to false.
const MyButton = (props: any) => {
return props.url ? <a className="my-btn" onClick={() => {
let win = window.open("http://www.google.com/", "_blank", "toolbar=yes,scrollbars=yes,resizable=yes,top=500,left=500,width=400,height=400");
console.log('Is open: ' + !win.closed);
}} target="_blank">My Button</a> : null;
};
Issue is that i don't see the window pop up?
One solution that works is to 'intercept' window.open() calls in the preload script. In the preload script you could create a new browser window and open it.
I have a <webview> in my Electron app. I'd like to have safe "foreign" communication, the way I would with an iframe through postMessage. So for example:
webview.executeJavaScript("window.parent.postMessage('all done!')");
Is my only choice for communication with this subwebview to turn on nodeIntegration so that I can use sendToHost? Turning on all of nodeIntegration just for this one feature seems like overkill.
You can access Electron APIs in the webview preload script, including IPC, even when nodeIntegration is disabled. Your preload script can inject functions into the global namespace that will then be accessible within the page loaded in the webview. A simple example:
webview-preload.js:
const { ipcRenderer } = require('electron')
global.pingHost = () => {
ipcRenderer.sendToHost('ping')
}
webview-index.html:
<script>
pingHost()
</script>
window-index.html:
<script>
const webview = document.getElementById('mywebview')
webview.addEventListener('ipc-message', event => {
// prints "ping"
console.log(event.channel)
})
</script>
Easiest way
Communication is
Note:
(main.js or app.js or background.js or process.js ) no need to pass (directly pass component to component),i succesffully implemented in electron:3.1.10
for print html webview.
Window To Webview
example1.html
<webview id="paper" style="width:300px;height:800px" src="file:///static/mywebview.html" nodeintegration></webview>
example1.js
var webview = document.getElementById("paper");
webview.send("ping",data);
getting data from mycomponent or window(i send directly form component)
mywebview.html
<!---what data you want show----!>
mywebview.js
const {
ipcRenderer
} = require('electron')
//data from window
ipcRenderer.on('ping', (e, data) => { console.log(data) })
webview to window
Webview to window(direct pass to component)
mywebview.js
ipcRenderer.sendToHost("readyCompanyInfo",data)
in my window eg i use vue (mycomponent.vue or mypage)
example1.html
const ipcRenderer = require("electron").ipcRenderer;
webview.addEventListener("ipc-message",(event)=>{
const {args,channel}=event;
if(channel=="readyCompanyInfo")
{
console.log(channel,args)
//here you can see data what u passed from webview to window
console.log(args[0])
}
})