i am working with electron#22.0.0 running on raspberry, and i need to support connecting to WIFI through captive portal. the captive portal being opened by window.open and handled with preload.js by mainWindow.webContents.setWindowOpenHandler method. i am trying to use in the child window (captive portal) the same keyboard that i use for the app which is 'electron-virtual-keyboard', the problem is that i cannot inject any js (i.e webFrame.executeJavaScript) since i cannot require any module inside the child window.
for example , the following code will throw exception 'require is undefined'
captivePortalPreload.js
i have tried enabling the following
webPreferences: { devTools: true, nodeIntegration: false, webSecurity: true, contextIsolation: true, enableRemoteModule: true, sandbox: false, preload: app.isPackaged ? path.join(__dirname, 'captivePortalPreload.js') : path.join(__dirname, '../../.erb/dll/captivePortalPreload.js'), },
Related
I have an issue with the firebase initialisation on my nativescript app (nativescript-vue).
I am using the nativescript-firebase plugin from https://github.com/EddyVerbruggen/nativescript-plugin-firebase
Here is my initialisation:
import { messaging } from "#nativescript/firebase/messaging";
import { firebase } from "#nativescript/firebase"
firebase.init({
onMessageReceivedCallback: function(message) {
//do stuff
}
}).then(function () {
//do stuff
},function (error) {
console.log("firebase.init error: " + error);
});
This works fine on android, but on ios, I get the error from my console.log
ReferenceError: FIROptions is not defined
My firebase.nativescript.json file is the following:
{
"using_ios": true,
"using_android": true,
"analytics": true,
"firestore": false,
"realtimedb": false,
"authentication": false,
"remote_config": false,
"performance_monitoring": false,
"external_push_client_only": false,
"messaging": true,
"in_app_messaging": false,
"crashlytics": false,
"storage": false,
"functions": false,
"facebook_auth": false,
"google_auth": false,
"admob": false,
"dynamic_links": false,
"ml_kit": false
}
I have tried removing and adding the plugin and running ns clean on my project but it didn't change anything.
Another issue I have is that I do not get prompted the questions (the ones that fill up the json file) when I add the plugin. On android I had to go to node_modules/#nativescrpt/firebase and run npm run config to get the questions. However, this command does nothing on ios. I have no error, in my terminal, but nothing happens.
I got it to work, the two issues were indeed linked. I had to run npm run config for the plugin to work correctly.
It turns out I was using an old version of npm. Updating npm and running npm run config again fixed my issue
I'm using electron for the first time at the same time as js and node, I'm trying to make an application for hobby and knowledge.
I'm facing a problem when implementing my script to open external links.
I've been using the doc to fix the problem, but I haven't seen anything to help me with that problem.
My ex-links.js
const electron = require("electron");
const { shell } = electron;
const exLinkBtn = document.getElementById("open-ex-link");
exLinkBtn.addEventListener("click", function() {
shell.openExternal("https://www.youtube.com/watch?v=ifXalt3MJtM");
});
I've already tried to place the slider.html inside index.html and yet I still get that error, so I left it as I currently have it inside an iframe.
<iframe src="slider.html" frameborder=0 width="1180" height="728" style="padding-left:198.5px;"></iframe>
I expect that by clicking the open-ex-link button it will open the link in the default browser.
The default nodeIntegration value is false. So you can set it to true to solve the issue.
app.on('ready', () => {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
});
});
But, nodeIntegration: true is a security risk when you are executing some untrusted remote code on your application. For example, when your application opens up a third party webpage, it would be a security risk because the third party webpage will have access to node runtime and can run malicious code on the user's filesystem. So it makes sense to set nodeIntegration: false which is the default now.
You can use preload scripts as they have access to require and other Node.js features.
The index.js would be like:
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})
The preload.js would be like:
const { remote } = require('electron');
let currentWindow = remote.BrowserWindow.getFocusedWindow();
window.closeCurrentWindow = function(){
currentWindow.close();
}
I would like to lint html angular template files via the command line, similar to:
ng lint
I would like to validate the Angular html templates to check they are valid and the variables are correct, so I can run this in a CI pipeline like Travis or AWS Codebuild.
Visual studio code runs Angular Language Services and can do this:
What I want is to capture these errors, so that I don't let invalid Angular html templates get into releases.
How can I achieve this?
What you are seeing here is in fact a Typescript error, not a lint error.
There is an option fullTemplateTypeCheck that allows you to capture such errors during build when AOT is activated:
This option tells the compiler to enable the binding expression validation phase of the template compiler which uses TypeScript to validate binding expressions.
This option is false by default.
Note: It is recommended to set this to true because this option will default to true in the future.
This can in fact slow down your build considerably, so what you can do if you only want to use this in the CI pipeline:
Create a new tsconfig.strict.json next to your tsconfig.app.json like this:
{
"extends": "./tsconfig.app.json",
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}
In angular.json add a new configuration "strictProd" under projects>YourProject>architect>build>configurations that looks like this:
"strictProd": {
"tsConfig": "src/tsconfig.app.strict.json",
"aot": true
[...your other prod settings here],
}
Run it with ng build -c strictProd
The best thing I have found is the html hint node package. You can read about it here: https://htmlhint.com/docs/user-guide/getting-started
Here is settings for the .htmlhintrc that work with Angular.
{
"tagname-lowercase": true,
"attr-lowercase": false,
"attr-value-double-quotes": true,
"attr-value-not-empty": false,
"attr-no-duplication": true,
"doctype-first": false,
"tag-pair": true,
"tag-self-close": true,
"empty-tag-not-self-closed": true,
"spec-char-escape": false,
"id-unique": false,
"src-not-empty": true,
"title-require": true,
"alt-require": true,
"doctype-html5": true,
"id-class-value": "true",
"style-disabled": true,
"inline-style-disabled": true,
"inline-script-disabled": true,
"space-tab-mixed-disabled": "true",
"id-class-ad-disabled": true,
"href-abs-or-rel": false,
"attr-unsafe-chars": true,
"head-script-disabled": true
}
So, I've followed a number of guides to set up Webpack, Electron, and React to make a desktop application. After finishing the setup, I got to work, and learned that I needed to require an IPC mechanism from the main and renderer in order to communicate.
import {ipcRenderer} from "electron";
Adding this to my renderer.js file causes the error Uncaught ReferenceError: require is not defined.
After taking my problem to some colleagues, it was suggested that in my main.js file I should change
webPreferences: {
nodeIntegration: false,
}
to
webPreferences: {
nodeIntegration: true,
}
Everywhere I've read on google has said very clearly that if safety is something you care about, this is not something you should do. However, every resource I've been able to come across for electron ipc has used the ipcRenderer.
Now, does every example on the internet have huge security flaws, or am I missing some key part here?
My questions are as follows.
Is it possible to use ipcRenderer without enabling nodeIntegration?
If it is, how do I do it, and why would so many resources exclude this information?
If it is not, what do I use?
If I'm asking the wrong question, or I missed something, or there are any other clear problems with the way I've asked this question please let me know, otherwise thanks in advance.
Is it possible to use ipcRenderer without enabling nodeIntegration?
It is possible, but fiddly. It can be done by using a preload script.
If it is, how do I do it, and why would so many resources exclude this information?
It is possible, using the preload script as indicated below. However, this is not considered secure. Most of the existing documentation does not show best security practices.
A more secure example is given afterwards.
// preload.js
const electron = require('electron');
process.once('loaded', () => {
global.ipcRenderer = electron.ipcRenderer;
});
// main.js
const {app, BrowserWindow} = require('electron');
app.on('ready', () => {
// Create the browser window.
win = new BrowserWindow({
backgroundColor: '#fff', // always set a bg color to enable font antialiasing!
webPreferences: {
preload: path.join(__dirname, './preload.js'),
nodeIntegration: false,
enableRemoteModule: false,
// contextIsolation: true,
// nativeWindowOpen: true,
// sandbox: true,
}
});
win.loadURL(`file://${path.join(__dirname, 'index.html')}`);
NOTE That the path to the preload script must be absolute and this can also
get complicated when using webpack/babel, as the output file may be a different path.
If it is not, what do I use?
Edit
As #Yannic pointed out, there is now another option supported by Electron, called contextBridge. This new option may solve the problem more simply. For info on contextBridge, check the electron docs: https://www.electronjs.org/docs/tutorial/context-isolation
However, even with contextBridge you should not be try to expose entire electron APIs, just a limited API you have designed for your app
As mentioned, although it is possible to use ipcRenderer as shown above, the current electron security recommendations recommend also enabling contextIsolation. This will make the above approach unusable as you can no longer add data to the global scope.
The most secure recommendation, AFAIK is to use addEventListener and postMessage instead, and use the preload script as a bridge between the renderer and the main scripts.
// preload.js
const { ipcRenderer } = require('electron');
process.once('loaded', () => {
window.addEventListener('message', event => {
// do something with custom event
const message = event.data;
if (message.myTypeField === 'my-custom-message') {
ipcRenderer.send('custom-message', message);
}
});
});
// main.js
const {app, ipcMain, BrowserWindow} = require('electron');
app.on('ready', () => {
ipcMain.on('custom-message', (event, message) => {
console.log('got an IPC message', e, message);
});
// Create the browser window.
win = new BrowserWindow({
backgroundColor: '#fff', // always set a bg color to enable font antialiasing!
webPreferences: {
preload: path.join(__dirname, './preload.js'),
nodeIntegration: false,
enableRemoteModule: false,
contextIsolation: true,
sandbox: true,
// nativeWindowOpen: true,
}
});
win.loadURL(`file://${path.join(__dirname, 'index.html')}`);
// renderer.js
window.postMessage({
myTypeField: 'my-custom-message',
someData: 123,
});
I packed our JS web-application by Electron.
There is following error when I trying to start this packed application:
text.js: Uncaught TypeError: require.nodeRequire is not a function
There is no function nodeRequire in our version of RequireJS.
As I understand version of RequireJSfor NodeJS is different from from version of RequireJSfor browsers.
What should I do to fix this problem?
Should I use in our web-application other version of RequireJS?
Or is it possible to configure Electron to avoid this error?
Electron provides a config that worked for me.
// In the main process
var mainWindow = new BrowserWindow({
webPreferences: { nodeIntegration: false }
});
The problem is not actually in Electron or RequireJS, but in the text.js loader. Do you actually need that loader?
Its how require.js is looking to load versus; how electron wants to load the webcontent. Mainly the masterconfig enviornment is not defined and so uses the problematic nodeRequire.
Following up on #Jose Rego's answer, which guided me in the right direction.
Provided you have the nodeIntegration set to false, you also need to ensure that the content is being loaded into the browser as an URL:
// Creazione della finestra del browser.
mainWindow = new BrowserWindow({ width: 800, height: 600,
webPreferences: { nodeIntegration: false } });
Then when you are loading your content, specify it to behave as a URL:
mainWindow.loadURL(
url.format({
pathname: path.join(__dirname, `[STATIC_CONTENT_PATH]`),
protocol: "file:",
slashes: true
})
);