Electron app: How do you use ipcRenderer.sendToHost()? - webview

In the Electron documentation for the webview tag, the following example is given to show how to communicate between the renderer process and the web page hosted in the webview:
With sendToHost method and ipc-message event you can easily communicate between guest page and embedder page:
// In embedder page.
const webview = document.getElementById('foo')
webview.addEventListener('ipc-message', (event) => {
console.log(event.channel)
// Prints "pong"
})
webview.send('ping')
// In guest page.
const {ipcRenderer} = require('electron')
ipcRenderer.on('ping', () => {
ipcRenderer.sendToHost('pong')
})
However, in my guest web page (inside the webview), I get Uncaught ReferenceError: require is not defined when I try to require('electron'), as indicated in the docs.
Is there something else I need to do to be able to require the ipcRenderer module from the guest web page?
Electron version: 1.4.6
Note: I'm not sure if this is important or not, but the page running inside my webview is served from a local server. In my top-level page in the renderer process, I do something like: document.getElementById("webview").src = "http://localhost:1234/...";.
Edit: It looks like serving my web page from a local server does not change anything. I have the same error after trying with a static HTML file. It looks like the example in the docs simply doesn't work, or I'm understanding it wrong.
// Simple foo.html somewhere on my computer
<script>
const {ipcRenderer} = require('electron')
ipcRenderer.on('ping', () => {
ipcRenderer.sendToHost('pong')
})
</script>
// In embedder page, in renderer process
document.getElementById("webview").src = "file://path/to/foo.html";
Output from the embedded page (inside the webview):
Uncaught ReferenceError: require is not defined

EDIT
For security reasons, the preferred way to use require in renderer processes is to use preload to inject only the minimum node integration your page requires. See point 2) of Electron's security recommendations. A minimal example for ipcRenderer:
// main.ts
const mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
preload: './preload.js'
}
})
mainWindow.loadURL('https://my-website.com')
// preload.js
const { ipcRenderer } = require('electron')
window.sendToElectron= function (channel) {
ipcRenderer.send(channel)
}
In your webpage you can now use window.sendToElectron("ping").
If you're using <webview> inside the renderer process, you can use <webview src="page.html" preload="./preload.js" /> to achieve the same result. So, that's what I would use to answer my original question, and inside preload.js I would inject a function that calls ipcRenderer.sendToHost("pong") in the global window.
Old answer (bad for security)
I had missed a vital point in the webview docs. To be able to call require from the page embedded inside the webview, you need to set the nodeintegration attribute on the webview tag:
<webview id="webview" nodeintegration />

Related

How access environment variables from a Framework Components in Astro?

I'm working in a project using Astro and I am using a component with VUE. For this project I need to access some env vars.
I am able to access from the Astro templates, but I can't find a way to get in the VUE component. Is this possible?
There is no way to do this without exposing the environment variables.
To do this, we have to move the function to an endpoint of our API that runs on the server side and make a request to execute it safely.
You can expose the env var as data to the Vue component like so...
Vue 2
<script>
const { PUBLIC_ENV_HERE } = import.meta.env;
export default {
data() {
return {
PUBLIC_ENV_HERE,
};
},
};
</script>
Vue 3 with script setup
<script setup>
const { PUBLIC_ENV_HERE } = import.meta.env;
</script>
Remember to prefix client side variables with PUBLIC - see https://docs.astro.build/en/guides/environment-variables/ for more info.

Not able to integrate AWS lex with web

Here is my index.html file. I have required loading lex-web-ui.js and config.js files in script but still getting the error.
The error I am getting is ChatBotUiLoader is not defined
<html>
<head>
<title>My Parent Page</title>
</head>
<body>
<h1>Welcome to my parent page</h1>
<!-- loader script -->
<script src="./dist/lex-web-ui.js"></script>
<script>
/*
The loader library creates a global object named ChatBotUiLoader
It includes the IframeLoader constructor
An instance of IframeLoader has the load function which kicks off
the load process
*/
// options for the loader constructor
var loaderOptions = {
// you can put the chatbot UI config in a JSON file
configUrl: './config.json',
// the full page chatbot UI that will be iframed
iframeSrcPath: './chatbot-index.html#/?lexWebUiEmbed=true'
};
// The following statement instantiates the IframeLoader
var iframeLoader = new ChatBotUiLoader.IframeLoader(loaderOptions);
// chatbot UI config
// The loader can also obtain these values from other sources such
// as a JSON file or events. The configUrl variable in the
// loaderOptions above can be used to put these config values in a file
// instead of explicitly passing it as an argument.
var chatbotUiConfig = {
ui: {
// origin of the parent site where you are including the chatbot UI
// set to window.location.origin since hosting on same site
parentOrigin: window.location.origin,
},
iframe: {
// origin hosting the HTML file that will be embedded in the iframe
// set to window.location.origin since hosting on same site
iframeOrigin: window.location.origin,
},
cognito: {
// Your Cognito Pool Id - this is required to provide AWS credentials
poolId: 'xxx'
},
lex: {
// Lex Bot Name in your account
botName: 'xxx'
}
};
// Call the load function which returns a promise that is resolved
// once the component is loaded or is rejected if there is an error
iframeLoader.load(chatbotUiConfig)
.then(function () {
console.log('iframe loaded');
})
.catch(function (err) {
console.error(err);
});
</script>
</body>
</html>
I am trying to integrate AWS lex on my website. I am using this repo https://github.com/aws-samples/aws-lex-web-ui/tree/master/dist
But getting an error: ChatBotUiLoader is not defined. Can anyone help?
enter image description here
Simply, the error is that an instance of ChatBotUiLoader cannot be created as the library/script containing that object was not found within the scope of the page.
It could be that the demo application is broken but the fix is fairly simple.
You need to include the lex-web-ui-loader.js script file (and its dependencies) in your web page to resolve the issue.

Handle url with .html extension in angular2 router?

We are working on a Angular2(created from angular-cli v1.0.0-beta.28.3) which connects to Salesforce via OAth's User-Agent Flow mechanism(https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_user_agent_oauth_flow.htm).
Here is the authentication code i've used in the code.
Here's the code which handles the callback after Authentication:
import { Component } from '#angular/core';
import { ForceService } from './force';
#Component({
template : ` `,
})
export class AuthComponent {
constructor(force : ForceService) {
var event = new CustomEvent("oauthCallback", {'detail': window.location.href});
window.opener.document.dispatchEvent(event);
window.close();
}
}
In Salesforce, we have something called Connected-App, where we configure the callback urls for the authentication. Callbacks url looks like below:
https://my.site.com/#/auth-callback. Angular2 router configuration uses useHash:true option as well.
Everything is working fine until the new requirement which needs only the callback url to point to something like this:
https://my.site.com/auth-callback.html
So the equivalent html code for above will be :
<html>
<script type="text/javascript">
var event = new CustomEvent("oauthCallback", {'detail': window.location.href});
window.opener.document.dispatchEvent(event);
window.close();
}
</script>
</html>
Problem, we face is after Authenticating, we are not able to access the access_token from the url and close the Authentication Window, since the routing is not properly redirecting to auth-callback.html. All we get is a blank screen with url changed to http://localhost:4200/#/access_token
Is there's a way to solve this issue without turning off useHash ?

Ajax Refresh doesn't work remotely

I am using the Kendo window right now and they have an ajax method meant to load in new content to the window. This works on my localhost but for some reasons stops when I publish the site to a remote server. The content is just never loaded in, I have debugged the javascript on the server and the ajax calls are being made. Any help would be appreciated.
This is the code I am using.
#(Html.Kendo().Window()
.Name("window")
.Title("test")
.Actions(Image => Image
.Custom("custom")
.Minimize()
.Maximize()
.Close()
)
//.LoadContentFrom(#Model.selectedModule, "Modules")
.Draggable()
.Resizable()
.Width(500)
.Modal(true)
.Height(500)
.Visible(false)
)
function test(link) {
var use = link.title;
var dialog = $("#window").data("kendoWindow");
dialog.refresh({
url: "/Modules/" + use
});
setTimeout("open()", 200);
};
function open() {
var dialog = $("#window").data("kendoWindow");
dialog.center();
dialog.open();
}
</Script>
In the end I took the suggestion and replaced the method with the URL helper. The codeblock is as follows.
function test(link) {
var use = link.data('url');
var dialog = $("#window").data("kendoWindow");
dialog.refresh({
url: use
});
setTimeout("open()", 200);
To me it sounds like the URL is not resolved when using the deploying envirment. Can you try and use the URL helper which MVC provides? Also you can use network tools of the browser to see what actually the server responded.

jquery mobile page refresh

I want to refresh a page without using data-ajax="false" in anchor tag and i want to show the loading spinner while linking the pages in jquerymobile.pls help me.
reloadPage (boolean, default: false)
Forces a reload of a page, even if it is already in the DOM of the
page container. Used only when the 'to' argument of changePage() is a
URL.
Source: http://jquerymobile.com/demos/1.1.0-rc.1/docs/api/methods.html
So basically you can use $.mobile.changePage() to change pages and you can pass it the preloadPage : true option when you want to reload a URL.
Here is a quick example of how to use $.mobile.changePage() for links that have the reload class:
$(document).delegate('a.reload', 'click', function () {
$.mobile.changePage('myPage.html', { reloadPage : true });
return false;
});
The default loader in jquery mobile appears while linking to pages, by adding the following code:
$("a").click(function() {
$.mobile.showPageLoadingMsg();
//Other things you want to do
});

Resources