"Not allowed to load local resource" with file image URL in Electron app - electron

I am working on a note taking Electron app that uses Markdown. Currently, I'm working on inserting images into notes (using the Markdown syntax).
When inserting an image, my main process copies the image into the notes directory, then returns a file:/// URL to the image file. However, when I try to render the image, it doesn't load - and I get the error Not allowed to load local resource: file:///Users/joe/notes/images/foo.jpg.
Is there a way I can configure Electron to allow these local image URLs?

Option 1
Turning the web security off
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000,
webPreferences: {
webSecurity: false
}
});
Option 2
You can create your own protocol like this answer
Also here is the user that answered that question

You need register a file protocol to remove the file:/// prefix.
import { protocol } from "electron";
app.whenReady().then(() => {
protocol.registerFileProtocol('file', (request, callback) => {
const pathname = decodeURI(request.url.replace('file:///', ''));
callback(pathname);
});
});
https://github.com/electron/electron/issues/23757#issuecomment-640146333

Related

Is there a way to load local files into HTML in Electron? Getting ERR_UNKNOWN_URL_SCHEME

I have an Electron app that's trying to load a local audio file into an HTML5 <audio> element. The path itself is fine file:///../song.mp3 and I've set webSecurity to false, but I'm still getting Failed to load resource: net::ERR_UNKNOWN_URL_SCHEME. From that same error, if I copy the address and paste it into my browser, I get the correct file.
Are there any other settings I need to change to get this to work?
Appreciate your time
I think this is a bug. The URL scheme of the file is not enabling as a URL scheme.
You can use this code below inside of app.on('ready'....:
protocol.registerFileProtocol('file', (request, cb) => {
const url = request.url.replace('file:///', '')
const decodedUrl = decodeURI(url)
try {
return cb(decodedUrl)
} catch (error) {
console.error('ERROR: registerLocalResourceProtocol: Could not get file path:', error)
}
})
it will be fixed

In Rally, is it possible to dynamically change script source so that I can load multiple apps?

I would like to have a drop down of app Names (or url parameter) and load the app on select: Something like:
Ext.define('TestPage', {
extend: 'Rally.app.App',
items: [{
xtype: 'container',
id: "appDiv"
}],
launch: function () {
var me = this;
me.add({
xtype: 'box',
autoEl: {
tag: 'iframe',
src: 'https://rally-apps.com/Test.CFD.html',
width: 1020,
height: 1000
}
});
}
});
But I get error: Blocked a frame with origin https://rally-apps.com" from accessing a cross-origin frame. Is there any other way I can achieve this?
That error is a standard browser security limitation, where code in one domain cannot access code in another one. You may be able to work around it by instead making an ajax request to that url to load the app content and then injecting it into your current app. Hard to say.
The other idea that comes to mind is just adding these apps to your subscription app catalog, so anyone can add them to any pages they like...

Electron, I can't use BrowserWindow to explore file system

I'm trying to show a folder of the machine running an Electron app, I already look and see I can load the url file:///d:/ on my machine and see the folder content but noway to do that with a BrowserWindow. I can see in the DevTools an error saying
Not allowed to load local resource.
Is there a workaround or any setup to be able to do that?
I use the following code:
ipcMain.on('openExplorer', (event, arg) => {
exploreWindow = new BrowserWindow({ width: 120, height: 82, title: "MyApp", icon: "assets/images/favicon.ico" });
exploreWindow.setTitle('Files Explorer');
addr = 'file:///d://' ;
console.log(addr);
exploreWindow.loadURL(addr);
exploreWindow.openDevTools();
});
For security reasons it is a good idea to not grant a BrowserWindow access to the filesystem. If you still want to do so you could use the inter process communication module to access the filesystem from your mainfile and send it to your BrowserWindow.
See:
Electron Documentation for ipcMain
Electron Documentation for ipcRenderer

Passing Data to Windows in Electron

I'm learning Electron and working with multiple windows and IPC. In my main script I have the following:
var storeWindow = new BrowserWindow({
width: 400,
height: 400,
show: false
});
ipc.on('show-store-edit', function(event, store) {
console.log(store);
storeWindow.loadURL('file://' + __dirname + '/app/store.html');
storeWindow.show();
});
And in my primary window's script, I have the following inside of a click event handler, pulling in a list of stores:
$.getJSON("http://localhost:8080/stores/" + item.id).done(function(store) {
ipc.send('show-store-edit', store);
});
On the console, I am printing the store data from my server. What I'm unclear on is how to get that data into the view for my storeWindow:store.html. I'm not even sure I'm handling the sequence of events correctly but they would be:
click Edit Store
get store data from server
open new window to display store data
or
click Edit Store
open new window to display store data
get store data from server
In the latter, I'm not sure how I would get the ID required to fetch the store from the storeWindow's script.
To send events to particular window you can use webContents.send(EVENT_NAME, ARGS) (see docs). webContents is a property of a window instance:
// main process
storeWindow.webContents.send('store-data', store);
To listen for this event being sent, you need a listener in a window process (renderer):
// renderer process
var ipcRenderer = require('electron').ipcRenderer;
ipcRenderer.on('store-data', function (event,store) {
console.log(store);
});
You need the ipcMain module to achieve this... As stated in the API "When used in the main process, it handles asynchronous and synchronous messages sent from a renderer process (web page). Messages sent from a renderer will be emitted to this module."
API Docs for the ipcMain module:
https://electronjs.org/docs/api/ipc-main
To use the ipcMain you need to have nodeIntegration enabled on webPreferences
win = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
}
})
Be careful this may cause security issues.
For example: Let's say we want to pass a configuration (json) file to the web page
(Triple dots (...) represent your code that is already placed inside the file, but is not relevant to this example)
main.js
...
const { readFileSync } = require('fs') // used to read files
const { ipcMain } = require('electron') // used to communicate asynchronously from the main process to renderer processes.
...
// function to read from a json file
function readConfig () {
const data = readFileSync('./package.json', 'utf8')
return data
}
...
// this is the event listener that will respond when we will request it in the web page
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg)
event.returnValue = readConfig()
})
...
index.html
...
<script>
<!-- import the module -->
const { ipcRenderer } = require('electron')
<!-- here we request our message and the event listener we added before, will respond and because it's JSON file we need to parse it -->
var config = JSON.parse(ipcRenderer.sendSync('synchronous-message', ''))
<!-- process our data however we want, in this example we print it on the browser console -->
console.log(config)
<!-- since we read our package.json file we can echo our electron app name -->
console.log(config.name)
</script>
To see the console of the browser you need to open the dev tools, either from the default Electron menu or from your code.
e.g. inside the createWindow() function
win.webContents.openDevTools()

trigger.io - Embed external website

I would like to embed an external website in my app, so I tried it with the tag here:
<iframe src="http://www.uniteich.at" frameborder="0" width="420" height="315"></iframe>
But I get the following error: "Unsafe JavaScript attempt to access frame with URL content://io.trigger.forge2dd999d0f14b11e1bc8612313d1adcbe/src/index.html from frame with URL http://www.uniteich.at/. Domains, protocols and ports must match."
So is there a good solution to embed a website in ios/android app with trigger.io?
Thanks in advance,
enne
EDIT: Ok, to make it more clear what I want: I would just like to load an external website as soon as a user clicks on a specific tabbar button at the bottom. I made this event-handler:
var dessertButton = forge.tabbar.addButton({
text: "Uniteich",
icon: "img/strawberry.png",
index: 2
}, function (button) {
button.onPressed.addListener(function () {
//LOAD EXTERNAL WEBSITE IN CONTENT CONTAINER HERE
});
});
Is that possible somehow?
This issue is cross domain requests. For more information read the same origin policy.
To get around this you will need to utilize forge.request. After adding www.uniteich.at to your config permissions first try the simple forge.get like this:
button.onPressed.addListener(function () {
var mainElement = document.getElementById("main");
forge.request.get("http://www.uniteich.at/index.html", function(content) {
mainElement.innerHTML = content;
},
function(error) {
mainElement.innerHTML = "<b>Error</b>" + error.message;
});
});
And if that does not work or not enough (I am not at my dev computer right now) you can utilize more options with forge.request.ajax.

Resources