Problems with Custom HTML Dialog in Electron - javascript

So first off, I know about the following question Custom HTML Dialog in Electron already exists. My question expands on this question when some problems came up on the latest version of electron.
So some context:
I actually started a project of mine on like a very old version on Electron(v2.0.5) that I already had cuz I was too lazy to update electron. I got a working dialog class that you could do something like this:
let dialog = new dialog_class("./pages/dialog.html")
dialog.display().then((response) => console.log(response));
However I had to update my version to the current(v9.1.1) so of course my dialog broke, but I can't figure out how/why.
I create my dialog very much like this:
constructor(link){
this.link = link;
this.window = new electron.remote.BrowserWindow({...});
}
display(){
return new Promise((callback)=>{
this.window.loadURL(...);//url.format function in place of ...
this.window.on(`close`, () => {
if (!this.cancelCloseEvent) callback(false);
});
}
}
destroy(){
this.window.closable = true;
this.widow.close();
}
However, when I run this function:
function openDialog(){
let dialog = new dialog_class("./pages/dialog.html")
dialog.display().then((response) => console.log(response));
}
I can open the dialog perfectly, but can only close the dialog once. Like I can open it, close it then open it again but can't close it again. When I try to close it a 2nd time it keeps the dialog open AND throws this:
electron/js2c/renderer_init.js:82 Uncaught TypeError: Object has been destroyed
at BrowserWindow.get (electron/js2c/browser_init.js:125)
at electron/js2c/browser_init.js:233
at IpcMainImpl.<anonymous> (electron/js2c/browser_init.js:233)
at IpcMainImpl.emit (events.js:223)
at WebContents.<anonymous> (electron/js2c/browser_init.js:173)
at WebContents.emit (events.js:223)
I don't know why this happens, as each time I run openDialog it should create a NEW BrowserWindow, so I don't know how it's referencing the old window.
Note: all the code shown here should be enough for my problem. But just in case heres the entire dialog_class: https://pastebin.com/7pAwZJHF
Edit:
Since I'm putting a bounty on this, I wanted people to be able to reproduce the issue. Heres all the code you'll need: https://github.com/Frustrated-Programmer/ElectronBug
However: I still think all the code relevant is still supplied in this question

dialog.js
display(context) {
return new Promise((cb) => {
electron.ipcRenderer.on("callback", (event, val) => {
this._cancelCloseEvent = true;
cb(val);
// this.destroy(); WRONG!!! Remove this and destory your window on test.js which is having this object instance
});
}
...
test.js
dialog.display().then(function(value) {
response.innerText = value;
dialog.destroy();
// dialog = null; unnecessary!
});

Related

how to fix Error: java.lang.ClassNotFoundException on frida

I'm trying to bypass a root detection mechanism on an android app using Frida, I've tried so many different scripts (frida code share) and different approaches (like hiding root) with no luck!
So I tried to locate the class and method responsible for checking if the device is rooted or not and changing it's return value.
This is my script :
setTimeout(function() { // avoid java.lang.ClassNotFoundException
Java.perform(function() {
var hook = Java.use("app.name.RootUtils");
console.log("info: hooking target class");
hook.isRooted.overload().implementation = function() {
console.log("info: entered target method");
return Java.use("java.lang.Boolean").$new(false);
}
});
},0);
If I inject this code normally it won't work because it looks like the isRooted method will get called before it
If I use spawn to run the app and change this method return value it fails with error :
frida.core.RPCException: Error: java.lang.ClassNotFoundException: Didn't find class ...
I've also tried spawning the app and then using objection to run "android root disable" but it will return this error :
frida.core.RPCException: TypeError: cannot read property 'getApplicationContext' of null
at getApplicationContext (src/android/lib/libjava.ts:21)
I'm not sure if this is a problem with Frida or my system or ...
I think if I was able to make my main code runs at exactly after the class gets loaded (like using a loop to check or using a hook) the problem would be fixed but I don't know how to write that kind of code in js for frida.
I'm on macOS 11.5.1 using python 3.9 and installed latest version of frida and objection
I've tested on one rooted phone with android 10 and an emulator with android 6
I was able to solve this issue with a simple yet not very technical solution.
I used a setInteval to run my hooking over and over until it gets to work, (as #Robert mentioned, I also needed to wrap hooking inside a try catch to prevent the code from stoping after first try)
This may not work for everyone but since it worked for me I will post the final code, may it helps someone else in the future :)
Java.perform(function() {
var it = setInterval(function(){
try{
var hook = Java.use("app.name.RootUtils");
console.log("info: hooking target class");
hook.isRooted.overload().implementation = function() {
console.log("info: entered target method");
clearInterval(it);
return Java.use("java.lang.Boolean").$new(false);
}
} catch(e) {
console.log("failed!");
}
},200); // runs every 200milisecods
});
PS : you may need to change interval time to match your app needs, it worked for me with 200 miliseconds.
Sometimes app would do encryptions in its class loader, you may need to replace Java.classFactory.loader with the app's customized class loader in order to make Java.use function properly.
Here's how it's done:
Java.perform(function() {
//get real classloader
//from http://www.lixiaopeng.top/article/63.html
var application = Java.use("android.app.Application");
var classloader;
application.attach.overload('android.content.Context')
.implementation = function(context) {
var result = this.attach(context); // run attach as it is
classloader = context.getClassLoader(); // get real classloader
Java.classFactory.loader = classloader;
return result;
}
//interesting classes
const interestingClassPath = "com.myApp.SometingInteresting";
interestingClass = Java.use(interestingClassPath);
//do whatever you like here
})
Class not found
How do you know the class is app.name.RootUtils have you decompiled to app using Jadx or apktool? How about the method where RootUtils.isRooted() is called? Is there any special code that loads the RootUtils class e.g. from a non-standard dex file included in the app? If the class is loaded from a special dex file you could hook this dex loading mechanism and first execute it and then install your hook for RootUtils.isRooted().
Alternatively assuming RootUtils.isRooted() is called only from one other method and does not use special code for loading the RootUtils class you could hook that method and use the this hook to install install your RootUtils.isRooted() hook.
Error handling
The correct way to handle errors in JavaScript is using try catch block, not the setTimeout function:
Java.perform(() => {
try {
var hook = Java.use("app.name.RootUtils");
...
} catch (e) {
console.log("Failed to hook root detection" + e);
}
}
Regarding your problems hooking the class

Nightwatch ERROR: Unable to locate element: using: css selector

I am a newbie to nightwatch and javascript and for the life of me I am getting stuck at some weird places. I am trying to do a simple test which just clicks on three different tab menu items one at a time. When I run the code I get an ERROR: Unable to locate element: "#Performing_AF" using: css selector.
If I go ahead and use the css selector directly opposed to using elements the code works. Can someone guide me as to where I am going wrong?
The URL I am testing is: https://www.nypl.org/
Here is /pages/homepage.js
var elements = {
searchbutton: '.nyplHomepageApp button[name = "Search Button"]',
Authortalksconversations: '.titleTabs #tab-0',
Exibitions: '.titleTabs #tab-1',
Performing_AF: '.titleTabs #tab-2',
Other_Events: '.titleTabs #tab-3',
DonateButton: '#donateButton',
Shop: '#shopTopLink',
loadicon: '.dcom-loader',
searchboxbutton: 'button[type="submit"]',
inputsearch: '.desktopSearch-form-inputBox #desktopSearch-form-searchInput'
};
var quicksearch = {
go: function()
{
this
.waitForElementVisible('body', 6000)
.api.pause(2000)
.click('#Exibitions')
.pause(2000)
.click('#Other_Events')
.pause(2000)
.click('#Performing_AF')
}
};
module.exports = {
elements,
commands: [quicksearch]
};
And here is tests/homepagetest.js
module.exports = {
'Q': function(browser) {
var goto = browser.page.homepage();
goto.go;
//browser.end();
}
}
As I mentioned in my comments above, if you remove all the pauses from the test it will work. I'm not exactly sure the reasons behind that. It would be better to use waitForElementVisible or waitForElementPresent whenever possible. pause() will make your tests flaky and unreliable.
The way you would use these is
click on a tab
wait for some element on that tab to be visible / present
click on the next tab and repeat
If you really would like to keep the pauses you can get it to work by adding a few variables at the top of your go function and using those variables instead of the #someElement syntax.
go: function() {
var exibitions = this.elements.Exibitions.selector;
var otherEvents = this.elements.Other_Events.selector;
var performingAf = this.elements.Performing_AF.selector;
this
.waitForElementVisible('body', 6000)
.api.pause(2000)
.click(exibitions)
.pause(2000)
.click(otherEvents)
.pause(2000)
.click(performingAf)
}
This works fine for me
ul.titleTabs > li#tab-2
Your css selector also works out for me. What is the error that you're facing?

Dinosaur game hack not working

I was making this hack for the google dinosaur game:
function speed(n) {
Runner.instance_.setSpeed(n);
}
function noHit() {
Runner.prototype.gameOver = function() {
console.log("");
}
}
function notNoHit() {
Runner.prototype.gameOver = function() {
this.playSound(this.soundFx.HIT);
vibrate(200);
this.stop();
this.crashed = true;
this.distanceMeter.acheivement = false;
this.tRex.update(100, Trex.status.CRASHED);
}
}
it is meant to be typed into the console, that way you don't have to edit the html of the page, which is pretty complicated (at least to me.) so, when i type it in, it returns undefined, as usual. when I use speed(n), it sets the speed to n. when i use noHit(), it makes it so i can't get hit. when i say notNoHit(), it returns undefined, as usual, but when i hit a cactus, it gives me an error:
Uncaught RefrenceError: vibrate is not defined
at Runner.gameOver (<anonymous>:14:3)
at Runner.update (data:text/html,chromewebdata:2005)
this kinda surprised me, because the way I did notNoHit() was to simply set the function back to what it was, instead of a junk command, (console.log("");) so i'm not really sure how to fix this.
Open the console of chrome browser write the below code it is working fine for me.
Runner.instance_.gameOver=()=>{}
Try this code by this Dinosaur will automatically jump when he will be near the obstacles
Runner.instance_.gameOver = function () {
this.playSound ( this.soundFx.HIT);
vibrate(500);
this.crashed = false;
//this.tRex.endJump ();
this.tRex.startJump (200);
// console.log (this.tRex)
}

CKEditor New Instance always unloaded

I'm using CKEditor in my Angular app and have a view that reloads my CKEditor instance every time users access a new model.
I'm using the following JS to initialize the editor:
var initEditor = function() {
$('.js-editor-wrap').html("<textarea id='editor'></textarea>");
var editor = CKEDITOR.replace('editor', {});
editor.on('loaded', function() {
console.log('editor loaded');
});
editor.on('instanceReady', function() {
console.log('instance ready')
});
}
And the following to destroy the editor:
var destroyEditor = function() {
if (CKEDITOR.instances['editor']) {
CKEDITOR.instances['editor'].destroy(true);
$('#editor').off().remove();
}
}
The first editor initialization works just as expected, but subsequent initializations create an editor instance with a status of "unloaded" that never triggers the "loaded" or "instanceReady" events. I'm not seeing any errors in the console.
Any ideas what might be causing this?
This is definitely a similar issue to the following, but different enough that I think it warrants its own question: CKEditor instance already exists
After a LOT more digging and thanks to the jsfiddle from Jey Dwork, I figured out where the issue is here. My CKEditor config file adds a couple of plugins that referenced lang files that were improperly named. For some reason, when these plugins were included together they caused the editor to not fully load during a second initialization.
Removing the lang files and reference to them in the plugin definitions resolved the issue. It's too bad that there wasn't some error that was triggered around this. All's well that ends well though.

jquery programmatic popup window

I'm new to Jquery, so please bear with me. I'm trying to create a function that will programmatically open popup windows. I'm running the following code in Firefox, and it seems to work except that the popup windows disregards the toolbar/menubar/scrollbars/resizable/location parameters (they are still visible/functional and I would like to disable all of them):
wparams[0] = {windowURL:"site.html",height:100,width:100,left:500,top:500,toolbar:0,menubar:01,scrollbars:0,resizable:0,location:0}
var launchWindow = function(p)
{
$('.popup').popupWindow(wparams[p]).trigger("click");
}
var begin = function()
{
launchWindow(0);
}
I would like the popups I'm using jQuery-swip popup plugin (http://swip.codylindley.com/popupWindowDemo.html), am wondering what's wrong with the above code.
Also, when I try to run this code in chrome/safari (typing begin(); in the console) it returns undefined, whereas in Firefox it runs. I'm also confused as to why this is happening.
Thanks.
I didn't understand 'when' you want to open the popup, if when the page complete loading, so it should be
$(document).ready(function() {
launchWindow(0);
});
Also can you explain to me why use trigger(click)??? As of the plugin documentation, this should work like that
var launchWindow = function(p)
{
$('.popup').popupWindow(wparams[p]);
}
Does this work?
wparams[0] = {windowURL:"site.html","height:100,width:100,left:500,top:500,toolbar:0,menubar:01,scrollbars:0,resizable:0,location:0"}
That's a weird way to define the "wparams" array - what happens if you do this:
var wparams = [
{windowURL:"site.html", height:100, width:100, left:500, top:500, toolbar:0, menubar:01, scrollbars:0, resizable:0, location:0}
];
It's not really clear why you're setting that up as an array; I guess maybe there might be other popup configurations stored in it. If that's the case, you'd just write them inside those square brackets, separated by commas.

Categories

Resources