I'm trying to figure out how to exchange messages between the main process and the BrowserView.
I've been using the ipc between the main process and the renderer process within a "simple" react renderer page.
But now, using the same technique, I do not see the received message in the console of the BrowserView, which, as far as I understand, seems to behave differently from a "normal" react renderer page.
And this SOF post seems confirm my hypothesis: Electron BrowserView Renderer process vs WebView
In preload I defined:
declare global {
interface Window {
api: {
electronIpcSend: (channel: string, ...arg: any) => void;
electronIpcOn: (channel: string, listener: (event: any, ...arg: any) => void) => void;
}
}
}
In main I have :
function createWindowTypeC (url_string: string) {
WindowTypeC = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: false,
sandbox: true,
nodeIntegrationInSubFrames: false,
webSecurity: true,
webviewTag: false,
preload: path.join(__dirname, "./preload/preload.js"), /* eng-disable PRELOAD_JS_CHECK */
}
})
// and load the index.html of the app.
// Emitted when the window is closed.
WindowTypeC.on('closed', () => {
WindowTypeC.removeBrowserView(view_C)
WindowTypeC = null
})
enforceInheritance(WindowTypeC.webContents)
// https://www.electronjs.org/docs/latest/api/browser-view
let view_C = new BrowserView()
view_C.webContents.once('did-finish-load', () => {
contents.focus()
view_C.webContents.send('ping', 'whoooooooooh!')
})
view_C.setAutoResize({
width: true,
height: true,
horizontal: true,
vertical: true
})
WindowTypeC.setBrowserView(view_C)
view_C.setBounds({ x: 0, y: 0, width: 800, height: 600 })
view_C.setBackgroundColor("#1e1e1e")
setTimeout(() => {
view_C.webContents.loadURL(url_string)
}, 200)
view_C.webContents.openDevTools({
mode: 'left'
})
}
While in the App_C.tsx I have:
import * as React from 'react';
function App_C(props) {
window.api.electronIpcOn('ping', (event, message) => {
console.log("App_C-window.api.electronIpcOn-ping-message: ", message)
})
window.api.electronIpcSend('pong', "Hello from App_C.tsx")
return (
<div id="outer-container" className='outer-container'>
<h1>App_C</h1>
</div>
);
}
export default App_C;
Executing the code, the page gets correctly rendered, but I do not see any message sent from the BrowserView to the renderer process.
Second, collateral, question, is: how to send a message on the way back, in the BrowserView sent by the renderer process?
And third question: how to interact with the page rendered by the BrowserView?
Related
I'm trying to build my electron application with electron-builder, I have successfully built front-end which was react and did also pass homepage: "./" in my package.json. I have also used hashbrowser as it was mentioned here
but still when I build my app, I get this message in console with white screen:
Not allowed to load local resource. I have passed webSecurity: false in webPreferences electron, It made error go away but didn't fix the problem and still getting white page.
this is my electron index.ts:
let mainWindow: BrowserWindow;
const createWidnow = () => {
mainWindowFunctions();
mainWindow = new BrowserWindow({
minHeight: 600,
minWidth: 800,
x: appXAndY.x,
y: appXAndY.y,
width: appWidthAndHeight.width,
height: appWidthAndHeight.height,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
preload: path.join(__dirname, "preload.js"),web
},
autoHideMenuBar: true,
});
mainWindow.loadURL(
isDev ? "http://localhost:3000/" : `file://${__dirname}/../build/index.html`
);
if (isDev) {
mainWindow.webContents.openDevTools();
}
}
app.whenReady().then(async () => {
createWidnow();
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWidnow();
}
});
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
db.close();
app.quit();
}
});
const mainWindowFunctions = () => {
const files = glob.sync(
path.join(__dirname, "./controllers/**/*.js").split(path.sep).join("/")
);
files.forEach((file) => {
require(file);
});
};
I tried webSecurity false but didn't help
The problem is with Electron Packager. Just use Electron Builder. Then you can get the installer using wix3.
im trying to open a link in a new browser window using a Electron App.
const test = () => {
const shell = window.require('electron').shell;
shell.openExternal("https://google.com");
}
When i do this, i get error "window.require is not a function"
I have ofcourse made my research on this, and found several "fixes" but none has worked for me. I have edited my webpack.config.js to this:
module.exports = {
configureWebpack: {
externals: {
'./cptable': 'var cptable'
},
resolve: {
fallback: {
'fs': false,
'crypto': false,
'path': false,
}
}
},
}
I have also made sure nodeIntegration enabled like so:
const mainWindow = new BrowserWindow({
width: 1280,
height: 720,
webPreferences: {
nodeIntegration: true
},
autoHideMenuBar: true,
resizable: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
```
still no success. any idea?
renderer.js - from your renderer send request.
const response = await window.electronAPI.openLinkPlease()
preload.js - you have this middleware where your request will receive to send to electron.
process.once("loaded", () => {
contextBridge.exposeInMainWorld('electronAPI', {
openLinkPlease: () => ipcRenderer.invoke('openLinkPlease'),
})
});
electron.js - here you will get your request to open and electron will open this url in your default browser.
First add at the very beginning const {shell} = require("electron"); to add shell capabilities and than after
preload: path.join(__dirname, 'preload.js'),
},
});
add
ipcMain.handle('openLinkPlease', () => {
shell.openExternal("https://google.com");
})
This is the screen how it works from my application
I have no idea what is happening here, basically I tried to print a document in electron using webContents.print, by silent print, but this error occurs and the printer only prints the document a single time, after that the print queue is filled with new orders, but the error still happening and the file is not printed.
Some code of what I am trying to do:
ipcMain.handle('imprimir', async (event, args) => {
console.log(args);
const ticket = new BrowserWindow({
width: 300,
height: 400,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false
}
});
ticket.loadFile('src/views/ticket.html')
.then(() => {
ticket.webContents.send('enviar-pedido', args);
var options = {
silent: true,
deviceName: 'HP Deskjet 2000 J210 series',
printBackground: true,
color: false,
margin: {
marginType: 'printableArea'
},
landscape: false,
pagesPerSheet: 1,
collate: false,
copies: 1,
/*pageSize: { height: 600, width: 353 }*/
}
ticket.webContents.print(options, (success, failureReason) => {
if (!success) {
console.log(failureReason);
}
console.log('Print Initiated');
ticket.close();
});
});
Note: I do not speak fluent English and this is my first question here, I am sorry if I commited some mistake.
I ran into this just the other day.
I determined the error does not appear with the BrowserWindow option
nodeIntegration: false
If you do not need nodeIntegration in the HTML loaded into the ticket window you should be able to turn this off.
I am looking to try to redirect users from "home.html" to "dashboard.html". I've searched far and wide, yet I haven't found an answer.
When creating your window with the BrowserWindow module, you would have used the method win.loadFile(filePath[, options]) to load your html file.
Once the logic to change pages is successful, all you need to do is execute the win.loadFile(filePath[, options]) line of code again with the path to your new file.
As win.loadFile(filePath[, options]) returns a promise, let's add a .then() statement as well (though not requried).
main.js (main thread)
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const nodePath = require("path");
let window;
function createWindow() {
const window = new electronBrowserWindow({
x: 0,
y: 0,
width: 800,
height: 600,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('home.html')
.then(() => { window.show(); });
return window;
}
electronApp.on('ready', () => {
window = createWindow();
});
// Run when logic to change to dashboard is successful.
function showDashboard() {
window.loadFile('dashboard.html')
.then(() => { window.show(); })
}
In my renderer I can emit an event to create a PDF. However, before writing to disk I'd like to first open the newly cerated PDF in another window. How can I circumvent the writing to the file system and use data as my source for loadURL?
My code so far:
ipcMain.on('view-pdf', (event, url) => {
let pdf
mainWindow.webContents.printToPDF({}, (error, data) => {
if (error) throw error
pdf = data
// what's the magic here to make pdf work?
})
const pdfWindow = new BrowserWindow({
width: 1024,
height: 800,
webPreferences: {
plugins: true,
webSecurity: false
}
})
pdfWindow.loadURL(pdf)
})
The async nature of Javascript is a beast. This works as expected:
ipcMain.on('view-pdf', (event, url) => {
mainWindow.webContents.printToPDF({}, (error, data) => {
if (error) throw error
const pdf = data.toString('base64')
const pdfWindow = new BrowserWindow({
width: 1024,
height: 800,
webPreferences: {
plugins: true,
webSecurity: false
}
})
pdfWindow.loadURL('data:application/pdf;base64,' + pdf)
})
})
The code is not perfect but this is how it works.