mirror of
https://github.com/webui-dev/webui.git
synced 2024-09-11 22:17:13 +03:00
Run formatter
This commit is contained in:
parent
1866d2573c
commit
8bf9bf2279
@ -8,7 +8,4 @@ IndentWrappedFunctionNames: true
|
||||
AccessModifierOffset: 0
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
PointerAlignment: Left
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: false
|
||||
AlignConsecutiveMacros: AcrossEmptyLines
|
||||
|
10
README.md
10
README.md
@ -107,10 +107,11 @@ Think of WebUI like a WebView controller, but instead of embedding the WebView c
|
||||
nmake
|
||||
```
|
||||
|
||||
**Windows SSL/TLS (*Optional*)**
|
||||
**Windows SSL/TLS (_Optional_)**
|
||||
|
||||
Download and install the OpenSSL pre-compiled binaries for Windows:
|
||||
- MSVC: [x64 OpenSSL v3.1.3](https://slproweb.com/download/Win64OpenSSL-3_1_3.msi) or [*32Bit*](https://slproweb.com/download/Win32OpenSSL-3_1_3.msi). Please check this [Wiki list](https://wiki.openssl.org/index.php/Binaries) for more info.
|
||||
|
||||
- MSVC: [x64 OpenSSL v3.1.3](https://slproweb.com/download/Win64OpenSSL-3_1_3.msi) or [_32Bit_](https://slproweb.com/download/Win32OpenSSL-3_1_3.msi). Please check this [Wiki list](https://wiki.openssl.org/index.php/Binaries) for more info.
|
||||
- MinGW: [Curl for Windows win OpenSSL](https://curl.se/windows/)
|
||||
|
||||
```powershell
|
||||
@ -131,7 +132,7 @@ Think of WebUI like a WebView controller, but instead of embedding the WebView c
|
||||
make CC=clang
|
||||
```
|
||||
|
||||
**Linux SSL/TLS (*Optional*)**
|
||||
**Linux SSL/TLS (_Optional_)**
|
||||
|
||||
```sh
|
||||
sudo apt update
|
||||
@ -145,11 +146,12 @@ Think of WebUI like a WebView controller, but instead of embedding the WebView c
|
||||
```
|
||||
|
||||
- **macOS**
|
||||
|
||||
```sh
|
||||
make
|
||||
```
|
||||
|
||||
**macOS SSL/TLS (*Optional*)**
|
||||
**macOS SSL/TLS (_Optional_)**
|
||||
|
||||
```sh
|
||||
brew install openssl
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
'use-strict' // Force strict mode for transpiled
|
||||
'use-strict'; // Force strict mode for transpiled
|
||||
|
||||
/*
|
||||
WebUI Bridge
|
||||
@ -15,54 +15,54 @@
|
||||
*/
|
||||
|
||||
//@ts-ignore use *.ts import real extension
|
||||
import { AsyncFunction, addRefreshableEventListener } from './utils.ts'
|
||||
import { AsyncFunction, addRefreshableEventListener } from './utils.ts';
|
||||
|
||||
type DataTypes = string | number | boolean | Uint8Array
|
||||
type DataTypes = string | number | boolean | Uint8Array;
|
||||
|
||||
class WebuiBridge {
|
||||
// WebUI settings
|
||||
#secure: boolean
|
||||
#token: number
|
||||
#port: number
|
||||
#winNum: number
|
||||
#bindList: unknown[] = []
|
||||
#log: boolean
|
||||
#winX: number
|
||||
#winY: number
|
||||
#winW: number
|
||||
#winH: number
|
||||
#secure: boolean;
|
||||
#token: number;
|
||||
#port: number;
|
||||
#winNum: number;
|
||||
#bindList: unknown[] = [];
|
||||
#log: boolean;
|
||||
#winX: number;
|
||||
#winY: number;
|
||||
#winW: number;
|
||||
#winH: number;
|
||||
// Internals
|
||||
#ws: WebSocket
|
||||
#wsStatus = false
|
||||
#wsStatusOnce = false
|
||||
#closeReason = 0
|
||||
#closeValue: string
|
||||
#hasEvents = false
|
||||
#callPromiseID = new Uint16Array(1)
|
||||
#callPromiseResolve: (((data: string) => unknown) | undefined)[] = []
|
||||
#allowNavigation = false
|
||||
#sendQueue: Uint8Array[] = []
|
||||
#isSending = false
|
||||
#ws: WebSocket;
|
||||
#wsStatus = false;
|
||||
#wsStatusOnce = false;
|
||||
#closeReason = 0;
|
||||
#closeValue: string;
|
||||
#hasEvents = false;
|
||||
#callPromiseID = new Uint16Array(1);
|
||||
#callPromiseResolve: (((data: string) => unknown) | undefined)[] = [];
|
||||
#allowNavigation = false;
|
||||
#sendQueue: Uint8Array[] = [];
|
||||
#isSending = false;
|
||||
// WebUI const
|
||||
#WEBUI_SIGNATURE = 221
|
||||
#CMD_JS = 254
|
||||
#CMD_JS_QUICK = 253
|
||||
#CMD_CLICK = 252
|
||||
#CMD_NAVIGATION = 251
|
||||
#CMD_CLOSE = 250
|
||||
#CMD_CALL_FUNC = 249
|
||||
#CMD_SEND_RAW = 248
|
||||
#CMD_NEW_ID = 247
|
||||
#CMD_MULTI = 246
|
||||
#MULTI_CHUNK_SIZE = 65500
|
||||
#PROTOCOL_SIZE = 8 // Protocol header size in bytes
|
||||
#PROTOCOL_SIGN = 0 // Protocol byte position: Signature (1 Byte)
|
||||
#PROTOCOL_TOKEN = 1 // Protocol byte position: Token (4 Bytes)
|
||||
#PROTOCOL_ID = 5 // Protocol byte position: ID (2 Bytes)
|
||||
#PROTOCOL_CMD = 7 // Protocol byte position: Command (1 Byte)
|
||||
#PROTOCOL_DATA = 8 // Protocol byte position: Data (n Byte)
|
||||
#Token = new Uint32Array(1)
|
||||
#Ping: Boolean = true
|
||||
#WEBUI_SIGNATURE = 221;
|
||||
#CMD_JS = 254;
|
||||
#CMD_JS_QUICK = 253;
|
||||
#CMD_CLICK = 252;
|
||||
#CMD_NAVIGATION = 251;
|
||||
#CMD_CLOSE = 250;
|
||||
#CMD_CALL_FUNC = 249;
|
||||
#CMD_SEND_RAW = 248;
|
||||
#CMD_NEW_ID = 247;
|
||||
#CMD_MULTI = 246;
|
||||
#MULTI_CHUNK_SIZE = 65500;
|
||||
#PROTOCOL_SIZE = 8; // Protocol header size in bytes
|
||||
#PROTOCOL_SIGN = 0; // Protocol byte position: Signature (1 Byte)
|
||||
#PROTOCOL_TOKEN = 1; // Protocol byte position: Token (4 Bytes)
|
||||
#PROTOCOL_ID = 5; // Protocol byte position: ID (2 Bytes)
|
||||
#PROTOCOL_CMD = 7; // Protocol byte position: Command (1 Byte)
|
||||
#PROTOCOL_DATA = 8; // Protocol byte position: Data (n Byte)
|
||||
#Token = new Uint32Array(1);
|
||||
#Ping: Boolean = true;
|
||||
constructor({
|
||||
secure,
|
||||
token,
|
||||
@ -75,206 +75,206 @@ class WebuiBridge {
|
||||
winW,
|
||||
winH,
|
||||
}: {
|
||||
secure: boolean
|
||||
token: number
|
||||
port: number
|
||||
winNum: number
|
||||
bindList: unknown[]
|
||||
log?: boolean
|
||||
winX: number
|
||||
winY: number
|
||||
winW: number
|
||||
winH: number
|
||||
secure: boolean;
|
||||
token: number;
|
||||
port: number;
|
||||
winNum: number;
|
||||
bindList: unknown[];
|
||||
log?: boolean;
|
||||
winX: number;
|
||||
winY: number;
|
||||
winW: number;
|
||||
winH: number;
|
||||
}) {
|
||||
// Constructor arguments are injected by webui.c
|
||||
this.#secure = secure
|
||||
this.#token = token
|
||||
this.#port = port
|
||||
this.#winNum = winNum
|
||||
this.#bindList = bindList
|
||||
this.#log = log
|
||||
this.#winX = winX
|
||||
this.#winY = winY
|
||||
this.#winW = winW
|
||||
this.#winH = winH
|
||||
this.#secure = secure;
|
||||
this.#token = token;
|
||||
this.#port = port;
|
||||
this.#winNum = winNum;
|
||||
this.#bindList = bindList;
|
||||
this.#log = log;
|
||||
this.#winX = winX;
|
||||
this.#winY = winY;
|
||||
this.#winW = winW;
|
||||
this.#winH = winH;
|
||||
// Token
|
||||
this.#Token[0] = this.#token
|
||||
this.#Token[0] = this.#token;
|
||||
// Instance
|
||||
if ('webui' in globalThis) {
|
||||
throw new Error('Sorry. WebUI is already defined, only one instance is allowed.')
|
||||
throw new Error('Sorry. WebUI is already defined, only one instance is allowed.');
|
||||
}
|
||||
// Positioning the current window
|
||||
if (this.#winX !== undefined && this.#winY !== undefined) {
|
||||
window.moveTo(this.#winX, this.#winY)
|
||||
window.moveTo(this.#winX, this.#winY);
|
||||
}
|
||||
// Resize the current window
|
||||
if (this.#winW !== undefined && this.#winH !== undefined) {
|
||||
window.resizeTo(this.#winW, this.#winH)
|
||||
window.resizeTo(this.#winW, this.#winH);
|
||||
}
|
||||
// WebSocket
|
||||
if (!('WebSocket' in window)) {
|
||||
alert('Sorry. WebSocket is not supported by your web browser.')
|
||||
if (!this.#log) globalThis.close()
|
||||
alert('Sorry. WebSocket is not supported by your web browser.');
|
||||
if (!this.#log) globalThis.close();
|
||||
}
|
||||
// Connect to the backend application
|
||||
this.#start()
|
||||
this.#start();
|
||||
// Handle navigation server side
|
||||
if ('navigation' in globalThis) {
|
||||
globalThis.navigation.addEventListener('navigate', (event) => {
|
||||
if (!this.#allowNavigation) {
|
||||
event.preventDefault()
|
||||
const url = new URL(event.destination.url)
|
||||
event.preventDefault();
|
||||
const url = new URL(event.destination.url);
|
||||
if (this.#hasEvents) {
|
||||
if (this.#log) console.log(`WebUI -> DOM -> Navigation Event [${url.href}]`)
|
||||
this.#sendEventNavigation(url.href)
|
||||
if (this.#log) console.log(`WebUI -> DOM -> Navigation Event [${url.href}]`);
|
||||
this.#sendEventNavigation(url.href);
|
||||
} else {
|
||||
this.#close(this.#CMD_NAVIGATION, url.href)
|
||||
this.#close(this.#CMD_NAVIGATION, url.href);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
// Handle all link click to prevent natural navigation
|
||||
// Rebind listener if user inject new html
|
||||
addRefreshableEventListener(document.body, 'a', 'click', (event) => {
|
||||
if (!this.#allowNavigation) {
|
||||
event.preventDefault()
|
||||
const { href } = event.target as HTMLAnchorElement
|
||||
event.preventDefault();
|
||||
const { href } = event.target as HTMLAnchorElement;
|
||||
if (this.#hasEvents) {
|
||||
if (this.#log) console.log(`WebUI -> DOM -> Navigation Click Event [${href}]`)
|
||||
this.#sendEventNavigation(href)
|
||||
if (this.#log) console.log(`WebUI -> DOM -> Navigation Click Event [${href}]`);
|
||||
this.#sendEventNavigation(href);
|
||||
} else {
|
||||
this.#close(this.#CMD_NAVIGATION, href)
|
||||
this.#close(this.#CMD_NAVIGATION, href);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
// Prevent F5 refresh
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (this.#log) return // Allowed in debug mode
|
||||
if (event.key === 'F5') event.preventDefault()
|
||||
})
|
||||
if (this.#log) return; // Allowed in debug mode
|
||||
if (event.key === 'F5') event.preventDefault();
|
||||
});
|
||||
onbeforeunload = () => {
|
||||
this.#close()
|
||||
}
|
||||
this.#close();
|
||||
};
|
||||
setTimeout(() => {
|
||||
if (!this.#wsStatusOnce) {
|
||||
this.#freezeUi()
|
||||
alert('Sorry. WebUI failed to connect to the backend application. Please try again.')
|
||||
if (!this.#log) globalThis.close()
|
||||
this.#freezeUi();
|
||||
alert('Sorry. WebUI failed to connect to the backend application. Please try again.');
|
||||
if (!this.#log) globalThis.close();
|
||||
}
|
||||
}, 1500)
|
||||
}, 1500);
|
||||
}
|
||||
#close(reason = 0, value = '') {
|
||||
this.#wsStatus = false
|
||||
this.#closeReason = reason
|
||||
this.#closeValue = value
|
||||
this.#ws.close()
|
||||
this.#wsStatus = false;
|
||||
this.#closeReason = reason;
|
||||
this.#closeValue = value;
|
||||
this.#ws.close();
|
||||
if (reason === this.#CMD_NAVIGATION) {
|
||||
if (this.#log) {
|
||||
console.log(`WebUI -> Close -> Navigation to [${value}]`)
|
||||
console.log(`WebUI -> Close -> Navigation to [${value}]`);
|
||||
}
|
||||
this.#allowNavigation = true
|
||||
globalThis.location.replace(this.#closeValue)
|
||||
this.#allowNavigation = true;
|
||||
globalThis.location.replace(this.#closeValue);
|
||||
} else {
|
||||
if (this.#log) {
|
||||
console.log(`WebUI -> Close.`)
|
||||
console.log(`WebUI -> Close.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
#freezeUi() {
|
||||
document.body.style.filter = 'contrast(1%)'
|
||||
document.body.style.filter = 'contrast(1%)';
|
||||
}
|
||||
#isTextBasedCommand(cmd: number): Boolean {
|
||||
if (cmd !== this.#CMD_SEND_RAW) return true
|
||||
return false
|
||||
if (cmd !== this.#CMD_SEND_RAW) return true;
|
||||
return false;
|
||||
}
|
||||
#getDataStrFromPacket(buffer: Uint8Array, startIndex: number): string {
|
||||
let stringBytes: number[] = []
|
||||
let stringBytes: number[] = [];
|
||||
for (let i = startIndex; i < buffer.length; i++) {
|
||||
if (buffer[i] === 0) {
|
||||
// Check for null byte
|
||||
break
|
||||
break;
|
||||
}
|
||||
stringBytes.push(buffer[i])
|
||||
stringBytes.push(buffer[i]);
|
||||
}
|
||||
// Convert the array of bytes to a string
|
||||
const stringText = new TextDecoder().decode(new Uint8Array(stringBytes))
|
||||
return stringText
|
||||
const stringText = new TextDecoder().decode(new Uint8Array(stringBytes));
|
||||
return stringText;
|
||||
}
|
||||
#getID(buffer: Uint8Array, index: number): number {
|
||||
if (index < 0 || index >= buffer.length - 1) {
|
||||
throw new Error('Index out of bounds or insufficient data.')
|
||||
throw new Error('Index out of bounds or insufficient data.');
|
||||
}
|
||||
const firstByte = buffer[index]
|
||||
const secondByte = buffer[index + 1]
|
||||
const combined = (secondByte << 8) | firstByte // Works only for little-endian
|
||||
return combined
|
||||
const firstByte = buffer[index];
|
||||
const secondByte = buffer[index + 1];
|
||||
const combined = (secondByte << 8) | firstByte; // Works only for little-endian
|
||||
return combined;
|
||||
}
|
||||
#addToken(buffer: Uint8Array, value: number, index: number): void {
|
||||
if (value < 0 || value > 0xffffffff) {
|
||||
throw new Error('Number is out of the range for 4 bytes representation.')
|
||||
throw new Error('Number is out of the range for 4 bytes representation.');
|
||||
}
|
||||
if (index < 0 || index > buffer.length - 4) {
|
||||
throw new Error('Index out of bounds or insufficient space in buffer.')
|
||||
throw new Error('Index out of bounds or insufficient space in buffer.');
|
||||
}
|
||||
// WebUI expect Little-endian (Work for Little/Big endian platforms)
|
||||
buffer[index] = value & 0xff // Least significant byte
|
||||
buffer[index + 1] = (value >>> 8) & 0xff
|
||||
buffer[index + 2] = (value >>> 16) & 0xff
|
||||
buffer[index + 3] = (value >>> 24) & 0xff // Most significant byte
|
||||
buffer[index] = value & 0xff; // Least significant byte
|
||||
buffer[index + 1] = (value >>> 8) & 0xff;
|
||||
buffer[index + 2] = (value >>> 16) & 0xff;
|
||||
buffer[index + 3] = (value >>> 24) & 0xff; // Most significant byte
|
||||
}
|
||||
#addID(buffer: Uint8Array, value: number, index: number): void {
|
||||
if (value < 0 || value > 0xffff) {
|
||||
throw new Error('Number is out of the range for 2 bytes representation.')
|
||||
throw new Error('Number is out of the range for 2 bytes representation.');
|
||||
}
|
||||
if (index < 0 || index > buffer.length - 2) {
|
||||
throw new Error('Index out of bounds or insufficient space in buffer.')
|
||||
throw new Error('Index out of bounds or insufficient space in buffer.');
|
||||
}
|
||||
// WebUI expect Little-endian (Work for Little/Big endian platforms)
|
||||
buffer[index] = value & 0xff // Least significant byte
|
||||
buffer[index + 1] = (value >>> 8) & 0xff // Most significant byte
|
||||
buffer[index] = value & 0xff; // Least significant byte
|
||||
buffer[index + 1] = (value >>> 8) & 0xff; // Most significant byte
|
||||
}
|
||||
#start() {
|
||||
this.#keepAlive()
|
||||
this.#callPromiseID[0] = 0
|
||||
this.#keepAlive();
|
||||
this.#callPromiseID[0] = 0;
|
||||
if (this.#bindList.includes(this.#winNum + '/')) {
|
||||
this.#hasEvents = true
|
||||
this.#hasEvents = true;
|
||||
}
|
||||
const url = (this.#secure ? "wss://localhost" : "ws://localhost")
|
||||
this.#ws = new WebSocket(`${url}:${this.#port}/_webui_ws_connect`)
|
||||
this.#ws.binaryType = 'arraybuffer'
|
||||
const url = this.#secure ? 'wss://localhost' : 'ws://localhost';
|
||||
this.#ws = new WebSocket(`${url}:${this.#port}/_webui_ws_connect`);
|
||||
this.#ws.binaryType = 'arraybuffer';
|
||||
this.#ws.onopen = () => {
|
||||
this.#wsStatus = true
|
||||
this.#wsStatusOnce = true
|
||||
if (this.#log) console.log('WebUI -> Connected')
|
||||
this.#clicksListener()
|
||||
}
|
||||
this.#wsStatus = true;
|
||||
this.#wsStatusOnce = true;
|
||||
if (this.#log) console.log('WebUI -> Connected');
|
||||
this.#clicksListener();
|
||||
};
|
||||
this.#ws.onerror = () => {
|
||||
if (this.#log) console.log('WebUI -> Connection Failed')
|
||||
this.#freezeUi()
|
||||
}
|
||||
if (this.#log) console.log('WebUI -> Connection Failed');
|
||||
this.#freezeUi();
|
||||
};
|
||||
this.#ws.onclose = (event) => {
|
||||
this.#wsStatus = false
|
||||
this.#wsStatus = false;
|
||||
if (this.#closeReason === this.#CMD_NAVIGATION) {
|
||||
if (this.#log) {
|
||||
console.log(`WebUI -> Connection closed du to Navigation to [${this.#closeValue}]`)
|
||||
console.log(`WebUI -> Connection closed du to Navigation to [${this.#closeValue}]`);
|
||||
}
|
||||
} else {
|
||||
if (this.#log) {
|
||||
console.log(`WebUI -> Connection lost (${event.code})`)
|
||||
this.#freezeUi()
|
||||
console.log(`WebUI -> Connection lost (${event.code})`);
|
||||
this.#freezeUi();
|
||||
} else {
|
||||
this.#closeWindowTimer()
|
||||
this.#closeWindowTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.#ws.onmessage = async (event) => {
|
||||
const buffer8 = new Uint8Array(event.data)
|
||||
if (buffer8.length < this.#PROTOCOL_SIZE) return
|
||||
if (buffer8[this.#PROTOCOL_SIGN] !== this.#WEBUI_SIGNATURE) return
|
||||
const buffer8 = new Uint8Array(event.data);
|
||||
if (buffer8.length < this.#PROTOCOL_SIZE) return;
|
||||
if (buffer8[this.#PROTOCOL_SIGN] !== this.#WEBUI_SIGNATURE) return;
|
||||
if (this.#isTextBasedCommand(buffer8[this.#PROTOCOL_CMD])) {
|
||||
// UTF8 Text based commands
|
||||
const callId = this.#getID(buffer8, this.#PROTOCOL_ID)
|
||||
const callId = this.#getID(buffer8, this.#PROTOCOL_ID);
|
||||
// Process Command
|
||||
switch (buffer8[this.#PROTOCOL_CMD]) {
|
||||
case this.#CMD_JS_QUICK:
|
||||
@ -286,27 +286,27 @@ class WebuiBridge {
|
||||
// 2: [ID]
|
||||
// 3: [CMD]
|
||||
// 4: [Script]
|
||||
const script = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA)
|
||||
const scriptSanitize = script.replace(/(?:\r\n|\r|\n)/g, '\n')
|
||||
if (this.#log) console.log(`WebUI -> CMD -> JS [${scriptSanitize}]`)
|
||||
const script = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
|
||||
const scriptSanitize = script.replace(/(?:\r\n|\r|\n)/g, '\n');
|
||||
if (this.#log) console.log(`WebUI -> CMD -> JS [${scriptSanitize}]`);
|
||||
// Get callback result
|
||||
let FunReturn = 'undefined'
|
||||
let FunError = false
|
||||
let FunReturn = 'undefined';
|
||||
let FunError = false;
|
||||
try {
|
||||
FunReturn = await AsyncFunction(scriptSanitize)()
|
||||
FunReturn = await AsyncFunction(scriptSanitize)();
|
||||
} catch (e) {
|
||||
FunError = true
|
||||
FunReturn = e.message
|
||||
FunError = true;
|
||||
FunReturn = e.message;
|
||||
}
|
||||
// Stop if this is a quick call
|
||||
if (buffer8[this.#PROTOCOL_CMD] === this.#CMD_JS_QUICK) return
|
||||
if (buffer8[this.#PROTOCOL_CMD] === this.#CMD_JS_QUICK) return;
|
||||
// Get the call return
|
||||
if (FunReturn === undefined) {
|
||||
FunReturn = 'undefined'
|
||||
FunReturn = 'undefined';
|
||||
}
|
||||
// Logging
|
||||
if (this.#log && !FunError) console.log(`WebUI -> CMD -> JS -> Return Success [${FunReturn}]`)
|
||||
if (this.#log && FunError) console.log(`WebUI -> CMD -> JS -> Return Error [${FunReturn}]`)
|
||||
if (this.#log && !FunError) console.log(`WebUI -> CMD -> JS -> Return Success [${FunReturn}]`);
|
||||
if (this.#log && FunError) console.log(`WebUI -> CMD -> JS -> Return Error [${FunReturn}]`);
|
||||
// Protocol
|
||||
// 0: [SIGNATURE]
|
||||
// 1: [TOKEN]
|
||||
@ -315,17 +315,21 @@ class WebuiBridge {
|
||||
// 4: [Error, Script Response]
|
||||
const Return8 = Uint8Array.of(
|
||||
this.#WEBUI_SIGNATURE,
|
||||
0, 0, 0, 0, // Token (4 Bytes)
|
||||
0, 0, // ID (2 Bytes)
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // Token (4 Bytes)
|
||||
0,
|
||||
0, // ID (2 Bytes)
|
||||
this.#CMD_JS,
|
||||
FunError ? 1 : 0,
|
||||
...new TextEncoder().encode(FunReturn),
|
||||
)
|
||||
this.#addToken(Return8, this.#token, this.#PROTOCOL_TOKEN)
|
||||
this.#addID(Return8, callId, this.#PROTOCOL_ID)
|
||||
this.#sendData(Return8)
|
||||
);
|
||||
this.#addToken(Return8, this.#token, this.#PROTOCOL_TOKEN);
|
||||
this.#addID(Return8, callId, this.#PROTOCOL_ID);
|
||||
this.#sendData(Return8);
|
||||
}
|
||||
break
|
||||
break;
|
||||
case this.#CMD_CALL_FUNC:
|
||||
{
|
||||
// Protocol
|
||||
@ -334,19 +338,19 @@ class WebuiBridge {
|
||||
// 2: [ID]
|
||||
// 3: [CMD]
|
||||
// 4: [Call Response]
|
||||
const callResponse = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA)
|
||||
const callResponse = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
|
||||
if (this.#log) {
|
||||
console.log(`WebUI -> CMD -> Call Response [${callResponse}]`)
|
||||
console.log(`WebUI -> CMD -> Call Response [${callResponse}]`);
|
||||
}
|
||||
if (this.#callPromiseResolve[callId]) {
|
||||
if (this.#log) {
|
||||
console.log(`WebUI -> CMD -> Resolving Response #${callId}...`)
|
||||
console.log(`WebUI -> CMD -> Resolving Response #${callId}...`);
|
||||
}
|
||||
this.#callPromiseResolve[callId]?.(callResponse)
|
||||
this.#callPromiseResolve[callId] = undefined
|
||||
this.#callPromiseResolve[callId]?.(callResponse);
|
||||
this.#callPromiseResolve[callId] = undefined;
|
||||
}
|
||||
}
|
||||
break
|
||||
break;
|
||||
|
||||
case this.#CMD_NAVIGATION:
|
||||
// Protocol
|
||||
@ -355,10 +359,10 @@ class WebuiBridge {
|
||||
// 2: [ID]
|
||||
// 3: [CMD]
|
||||
// 4: [URL]
|
||||
const url = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA)
|
||||
console.log(`WebUI -> CMD -> Navigation [${url}]`)
|
||||
this.#close(this.#CMD_NAVIGATION, url)
|
||||
break
|
||||
const url = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
|
||||
console.log(`WebUI -> CMD -> Navigation [${url}]`);
|
||||
this.#close(this.#CMD_NAVIGATION, url);
|
||||
break;
|
||||
case this.#CMD_NEW_ID:
|
||||
// Protocol
|
||||
// 0: [SIGNATURE]
|
||||
@ -366,22 +370,22 @@ class WebuiBridge {
|
||||
// 2: [ID]
|
||||
// 3: [CMD]
|
||||
// 4: [New Element]
|
||||
const newElement = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA)
|
||||
console.log(`WebUI -> CMD -> New Bind ID [${newElement}]`)
|
||||
if (!this.#bindList.includes(newElement)) this.#bindList.push(newElement)
|
||||
break
|
||||
const newElement = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
|
||||
console.log(`WebUI -> CMD -> New Bind ID [${newElement}]`);
|
||||
if (!this.#bindList.includes(newElement)) this.#bindList.push(newElement);
|
||||
break;
|
||||
case this.#CMD_CLOSE:
|
||||
// Protocol
|
||||
// 0: [SIGNATURE]
|
||||
// 1: [TOKEN]
|
||||
// 2: [ID]
|
||||
// 3: [CMD]
|
||||
if (!this.#log) globalThis.close()
|
||||
if (!this.#log) globalThis.close();
|
||||
else {
|
||||
console.log(`WebUI -> CMD -> Close`)
|
||||
this.#ws.close()
|
||||
console.log(`WebUI -> CMD -> Close`);
|
||||
this.#ws.close();
|
||||
}
|
||||
break
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Raw-binary based commands
|
||||
@ -394,87 +398,89 @@ class WebuiBridge {
|
||||
// 3: [CMD]
|
||||
// 4: [Function,Null,Raw Data]
|
||||
// Get function name
|
||||
const functionName: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA)
|
||||
const functionName: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
|
||||
// Get the raw data
|
||||
const rawDataIndex: number = 2 + functionName.length + 1
|
||||
const userRawData = buffer8.subarray(rawDataIndex)
|
||||
if (this.#log) console.log(`WebUI -> CMD -> Send Raw ${buffer8.length} bytes to [${functionName}()]`)
|
||||
const rawDataIndex: number = 2 + functionName.length + 1;
|
||||
const userRawData = buffer8.subarray(rawDataIndex);
|
||||
if (this.#log) console.log(`WebUI -> CMD -> Send Raw ${buffer8.length} bytes to [${functionName}()]`);
|
||||
// Call the user function, and pass the raw data
|
||||
if (typeof window[functionName] === 'function') window[functionName](userRawData)
|
||||
else await AsyncFunction(functionName + '(userRawData)')()
|
||||
break
|
||||
if (typeof window[functionName] === 'function') window[functionName](userRawData);
|
||||
else await AsyncFunction(functionName + '(userRawData)')();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
#keepAlive = async () => {
|
||||
while (true) {
|
||||
if (this.#Ping) {
|
||||
// Some web browsers may close the connection
|
||||
// let's send a void message to keep WS open
|
||||
this.#sendData(new TextEncoder().encode('ping'))
|
||||
this.#sendData(new TextEncoder().encode('ping'));
|
||||
} else {
|
||||
// There is an active communication
|
||||
this.#Ping = true
|
||||
this.#Ping = true;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 20000))
|
||||
await new Promise((resolve) => setTimeout(resolve, 20000));
|
||||
}
|
||||
}
|
||||
};
|
||||
#clicksListener() {
|
||||
Object.keys(window).forEach((key) => {
|
||||
if (/^on(click)/.test(key)) {
|
||||
globalThis.addEventListener(key.slice(2), (event) => {
|
||||
if (!(event.target instanceof HTMLElement)) return
|
||||
if (!(event.target instanceof HTMLElement)) return;
|
||||
if (
|
||||
this.#hasEvents ||
|
||||
(event.target.id !== '' && this.#bindList.includes(this.#winNum + '/' + event.target?.id))
|
||||
) {
|
||||
this.#sendClick(event.target.id)
|
||||
this.#sendClick(event.target.id);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
async #sendData(packet: Uint8Array) {
|
||||
this.#Ping = false
|
||||
if (!this.#wsStatus || packet === undefined)
|
||||
return
|
||||
// Enqueue the packet
|
||||
this.#sendQueue.push(packet)
|
||||
if (this.#isSending)
|
||||
return
|
||||
this.#isSending = true
|
||||
while (this.#sendQueue.length > 0) {
|
||||
const currentPacket = this.#sendQueue.shift()!
|
||||
if (currentPacket.length < this.#MULTI_CHUNK_SIZE) {
|
||||
this.#ws.send(currentPacket.buffer)
|
||||
} else {
|
||||
// Pre-packet to let WebUI be ready for multi packet
|
||||
const pre_packet = Uint8Array.of(
|
||||
this.#WEBUI_SIGNATURE,
|
||||
0, 0, 0, 0, // Token (4 Bytes)
|
||||
0, 0, // ID (2 Bytes)
|
||||
this.#CMD_MULTI,
|
||||
...new TextEncoder().encode(currentPacket.length.toString()),
|
||||
0,
|
||||
)
|
||||
this.#ws.send(pre_packet.buffer)
|
||||
// Send chunks
|
||||
let offset = 0
|
||||
const sendChunk = async () => {
|
||||
if (offset < currentPacket.length) {
|
||||
const chunkSize = Math.min(this.#MULTI_CHUNK_SIZE, currentPacket.length - offset)
|
||||
const chunk = currentPacket.subarray(offset, offset + chunkSize)
|
||||
this.#ws.send(chunk)
|
||||
offset += chunkSize
|
||||
await sendChunk()
|
||||
}
|
||||
}
|
||||
await sendChunk()
|
||||
}
|
||||
}
|
||||
this.#isSending = false
|
||||
}
|
||||
this.#Ping = false;
|
||||
if (!this.#wsStatus || packet === undefined) return;
|
||||
// Enqueue the packet
|
||||
this.#sendQueue.push(packet);
|
||||
if (this.#isSending) return;
|
||||
this.#isSending = true;
|
||||
while (this.#sendQueue.length > 0) {
|
||||
const currentPacket = this.#sendQueue.shift()!;
|
||||
if (currentPacket.length < this.#MULTI_CHUNK_SIZE) {
|
||||
this.#ws.send(currentPacket.buffer);
|
||||
} else {
|
||||
// Pre-packet to let WebUI be ready for multi packet
|
||||
const pre_packet = Uint8Array.of(
|
||||
this.#WEBUI_SIGNATURE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // Token (4 Bytes)
|
||||
0,
|
||||
0, // ID (2 Bytes)
|
||||
this.#CMD_MULTI,
|
||||
...new TextEncoder().encode(currentPacket.length.toString()),
|
||||
0,
|
||||
);
|
||||
this.#ws.send(pre_packet.buffer);
|
||||
// Send chunks
|
||||
let offset = 0;
|
||||
const sendChunk = async () => {
|
||||
if (offset < currentPacket.length) {
|
||||
const chunkSize = Math.min(this.#MULTI_CHUNK_SIZE, currentPacket.length - offset);
|
||||
const chunk = currentPacket.subarray(offset, offset + chunkSize);
|
||||
this.#ws.send(chunk);
|
||||
offset += chunkSize;
|
||||
await sendChunk();
|
||||
}
|
||||
};
|
||||
await sendChunk();
|
||||
}
|
||||
}
|
||||
this.#isSending = false;
|
||||
}
|
||||
#sendClick(elem: string) {
|
||||
if (this.#wsStatus) {
|
||||
// Protocol
|
||||
@ -507,17 +513,17 @@ class WebuiBridge {
|
||||
0, // ID (2 Bytes)
|
||||
this.#CMD_CLICK,
|
||||
0,
|
||||
)
|
||||
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN)
|
||||
);
|
||||
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
|
||||
// this.#addID(packet, 0, this.#PROTOCOL_ID)
|
||||
this.#sendData(packet)
|
||||
if (this.#log) console.log(`WebUI -> Send Click [${elem}]`)
|
||||
this.#sendData(packet);
|
||||
if (this.#log) console.log(`WebUI -> Send Click [${elem}]`);
|
||||
}
|
||||
}
|
||||
#sendEventNavigation(url: string) {
|
||||
if (url !== '') {
|
||||
if (this.#hasEvents) {
|
||||
if (this.#log) console.log(`WebUI -> Send Navigation Event [${url}]`)
|
||||
if (this.#log) console.log(`WebUI -> Send Navigation Event [${url}]`);
|
||||
if (this.#wsStatus && this.#hasEvents) {
|
||||
const packet = Uint8Array.of(
|
||||
// Protocol
|
||||
@ -527,60 +533,64 @@ class WebuiBridge {
|
||||
// 3: [CMD]
|
||||
// 4: [URL]
|
||||
this.#WEBUI_SIGNATURE,
|
||||
0, 0, 0, 0, // Token (4 Bytes)
|
||||
0, 0, // ID (2 Bytes)
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // Token (4 Bytes)
|
||||
0,
|
||||
0, // ID (2 Bytes)
|
||||
this.#CMD_NAVIGATION,
|
||||
...new TextEncoder().encode(url),
|
||||
)
|
||||
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN)
|
||||
);
|
||||
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
|
||||
// this.#addID(packet, 0, this.#PROTOCOL_ID)
|
||||
this.#sendData(packet)
|
||||
this.#sendData(packet);
|
||||
}
|
||||
} else {
|
||||
if (this.#log) console.log(`WebUI -> Navigation To [${url}]`)
|
||||
this.#allowNavigation = true
|
||||
globalThis.location.replace(url)
|
||||
if (this.#log) console.log(`WebUI -> Navigation To [${url}]`);
|
||||
this.#allowNavigation = true;
|
||||
globalThis.location.replace(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
#closeWindowTimer() {
|
||||
setTimeout(function () {
|
||||
globalThis.close()
|
||||
}, 1000)
|
||||
globalThis.close();
|
||||
}, 1000);
|
||||
}
|
||||
#toUint16(value: number): number {
|
||||
return value & 0xffff
|
||||
return value & 0xffff;
|
||||
}
|
||||
#callPromise(fn: string, ...args: DataTypes[]) {
|
||||
--this.#callPromiseID[0]
|
||||
const callId = this.#toUint16(this.#callPromiseID[0])
|
||||
--this.#callPromiseID[0];
|
||||
const callId = this.#toUint16(this.#callPromiseID[0]);
|
||||
// Combine lengths
|
||||
let argsLengths = args
|
||||
.map((arg) => {
|
||||
if (typeof arg === 'object') {
|
||||
// Uint8Array
|
||||
return arg.length
|
||||
return arg.length;
|
||||
} else {
|
||||
// string, number, boolean
|
||||
return new TextEncoder().encode(arg.toString()).length
|
||||
return new TextEncoder().encode(arg.toString()).length;
|
||||
}
|
||||
})
|
||||
.join(';');
|
||||
// Combine values
|
||||
let argsValues: Uint8Array = new Uint8Array()
|
||||
let argsValues: Uint8Array = new Uint8Array();
|
||||
for (const arg of args) {
|
||||
let buffer: Uint8Array
|
||||
let buffer: Uint8Array;
|
||||
if (typeof arg === 'object') {
|
||||
buffer = arg // Uint8Array
|
||||
buffer = arg; // Uint8Array
|
||||
} else {
|
||||
// string, number, boolean
|
||||
buffer = new TextEncoder().encode(arg.toString())
|
||||
buffer = new TextEncoder().encode(arg.toString());
|
||||
}
|
||||
const temp = new Uint8Array(argsValues.length + buffer.length + 1)
|
||||
temp.set(argsValues, 0)
|
||||
temp.set(buffer, argsValues.length)
|
||||
temp[argsValues.length + buffer.length] = 0x00
|
||||
argsValues = temp
|
||||
const temp = new Uint8Array(argsValues.length + buffer.length + 1);
|
||||
temp.set(argsValues, 0);
|
||||
temp.set(buffer, argsValues.length);
|
||||
temp[argsValues.length + buffer.length] = 0x00;
|
||||
argsValues = temp;
|
||||
}
|
||||
// Protocol
|
||||
// 0: [SIGNATURE]
|
||||
@ -590,21 +600,25 @@ class WebuiBridge {
|
||||
// 4: [Fn, Null, {LenLen...}, Null, {Data,Null,Data,Null...}]
|
||||
const packet = Uint8Array.of(
|
||||
this.#WEBUI_SIGNATURE,
|
||||
0, 0, 0, 0, // Token (4 Bytes)
|
||||
0, 0, // ID (2 Bytes)
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // Token (4 Bytes)
|
||||
0,
|
||||
0, // ID (2 Bytes)
|
||||
this.#CMD_CALL_FUNC,
|
||||
...new TextEncoder().encode(fn),
|
||||
0,
|
||||
...new TextEncoder().encode(argsLengths),
|
||||
0,
|
||||
...argsValues,
|
||||
)
|
||||
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN)
|
||||
this.#addID(packet, callId, this.#PROTOCOL_ID)
|
||||
);
|
||||
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
|
||||
this.#addID(packet, callId, this.#PROTOCOL_ID);
|
||||
return new Promise((resolve) => {
|
||||
this.#callPromiseResolve[callId] = resolve
|
||||
this.#sendData(packet)
|
||||
})
|
||||
this.#callPromiseResolve[callId] = resolve;
|
||||
this.#sendData(packet);
|
||||
});
|
||||
}
|
||||
// -- APIs --------------------------
|
||||
/**
|
||||
@ -616,22 +630,22 @@ class WebuiBridge {
|
||||
* @example - const res = await webui.call("myID", 123, true, "Hi", new Uint8Array([0x42, 0x43, 0x44]))
|
||||
*/
|
||||
async call(fn: string, ...args: DataTypes[]): Promise<DataTypes> {
|
||||
if (!fn) return Promise.reject(new SyntaxError('No binding name is provided'))
|
||||
if (!fn) return Promise.reject(new SyntaxError('No binding name is provided'));
|
||||
|
||||
if (!this.#wsStatus) return Promise.reject(new Error('WebSocket is not connected'))
|
||||
if (!this.#wsStatus) return Promise.reject(new Error('WebSocket is not connected'));
|
||||
|
||||
// Check binding list
|
||||
if (!this.#hasEvents && !this.#bindList.includes(`${this.#winNum}/${fn}`))
|
||||
return Promise.reject(new ReferenceError(`No binding was found for "${fn}"`))
|
||||
return Promise.reject(new ReferenceError(`No binding was found for "${fn}"`));
|
||||
|
||||
// Call backend and wait for response
|
||||
if (this.#log) console.log(`WebUI -> Calling [${fn}(...)]`)
|
||||
const response = (await this.#callPromise(fn, ...args)) as string
|
||||
if (this.#log) console.log(`WebUI -> Calling [${fn}(...)]`);
|
||||
const response = (await this.#callPromise(fn, ...args)) as string;
|
||||
|
||||
// WebUI lib accept `DataTypes` but return only string
|
||||
if (typeof response !== 'string') return ''
|
||||
if (typeof response !== 'string') return '';
|
||||
|
||||
return response
|
||||
return response;
|
||||
}
|
||||
/**
|
||||
* Active or deactivate webui debug logging
|
||||
@ -640,11 +654,11 @@ class WebuiBridge {
|
||||
*/
|
||||
setLogging(status: boolean) {
|
||||
if (status) {
|
||||
console.log('WebUI -> Log Enabled.')
|
||||
this.#log = true
|
||||
console.log('WebUI -> Log Enabled.');
|
||||
this.#log = true;
|
||||
} else {
|
||||
console.log('WebUI -> Log Disabled.')
|
||||
this.#log = false
|
||||
console.log('WebUI -> Log Disabled.');
|
||||
this.#log = false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -653,7 +667,7 @@ class WebuiBridge {
|
||||
* @param data - text string
|
||||
*/
|
||||
encode(data: string): string {
|
||||
return btoa(data)
|
||||
return btoa(data);
|
||||
}
|
||||
/**
|
||||
* Decode base64 string into text
|
||||
@ -661,15 +675,15 @@ class WebuiBridge {
|
||||
* @param data - base64 string
|
||||
*/
|
||||
decode(data: string): string {
|
||||
return atob(data)
|
||||
return atob(data);
|
||||
}
|
||||
}
|
||||
// Export
|
||||
type webui = WebuiBridge
|
||||
export default webui
|
||||
export type { WebuiBridge }
|
||||
type webui = WebuiBridge;
|
||||
export default webui;
|
||||
export type { WebuiBridge };
|
||||
// Wait for the html to be parsed
|
||||
addEventListener('load', () => {
|
||||
document.body.addEventListener('contextmenu', (event) => event.preventDefault())
|
||||
addRefreshableEventListener(document.body, 'input', 'contextmenu', (event) => event.stopPropagation())
|
||||
})
|
||||
document.body.addEventListener('contextmenu', (event) => event.preventDefault());
|
||||
addRefreshableEventListener(document.body, 'input', 'contextmenu', (event) => event.stopPropagation());
|
||||
});
|
||||
|
@ -169,7 +169,8 @@ WEBUI_EXPORT size_t webui_new_window(void);
|
||||
WEBUI_EXPORT size_t webui_new_window_id(size_t window_number);
|
||||
|
||||
/**
|
||||
* @brief Get a free window number that can be used with `webui_new_window_id()`.
|
||||
* @brief Get a free window number that can be used with
|
||||
* `webui_new_window_id()`.
|
||||
*
|
||||
* @return Returns the first available free window number. Starting from 1.
|
||||
*
|
||||
@ -178,7 +179,8 @@ WEBUI_EXPORT size_t webui_new_window_id(size_t window_number);
|
||||
WEBUI_EXPORT size_t webui_get_new_window_id(void);
|
||||
|
||||
/**
|
||||
* @brief Bind a specific html element click event with a function. Empty element means all events.
|
||||
* @brief Bind a specific html element click event with a function. Empty
|
||||
* element means all events.
|
||||
*
|
||||
* @param window The window number
|
||||
* @param element The HTML ID
|
||||
@ -191,14 +193,16 @@ WEBUI_EXPORT size_t webui_get_new_window_id(void);
|
||||
WEBUI_EXPORT size_t webui_bind(size_t window, const char* element, void (*func)(webui_event_t* e));
|
||||
|
||||
/**
|
||||
* @brief Show a window using embedded HTML, or a file. If the window is already open, it will be refreshed.
|
||||
* @brief Show a window using embedded HTML, or a file. If the window is already
|
||||
* open, it will be refreshed.
|
||||
*
|
||||
* @param window The window number
|
||||
* @param content The HTML, Or a local file
|
||||
*
|
||||
* @return Returns True if showing the window is successed.
|
||||
*
|
||||
* @example webui_show(myWindow, "<html>...</html>"); | webui_show(myWindow, "index.html");
|
||||
* @example webui_show(myWindow, "<html>...</html>"); | webui_show(myWindow,
|
||||
* "index.html");
|
||||
*/
|
||||
WEBUI_EXPORT bool webui_show(size_t window, const char* content);
|
||||
|
||||
@ -211,7 +215,8 @@ WEBUI_EXPORT bool webui_show(size_t window, const char* content);
|
||||
*
|
||||
* @return Returns True if showing the window is successed.
|
||||
*
|
||||
* @example webui_show_browser(myWindow, "<html>...</html>", Chrome); | webui_show(myWindow, "index.html", Firefox);
|
||||
* @example webui_show_browser(myWindow, "<html>...</html>", Chrome); |
|
||||
* webui_show(myWindow, "index.html", Firefox);
|
||||
*/
|
||||
WEBUI_EXPORT bool webui_show_browser(size_t window, const char* content, size_t browser);
|
||||
|
||||
@ -268,7 +273,8 @@ WEBUI_EXPORT void webui_exit(void);
|
||||
WEBUI_EXPORT bool webui_set_root_folder(size_t window, const char* path);
|
||||
|
||||
/**
|
||||
* @brief Set the web-server root folder path for all windows. Should be used before `webui_show()`.
|
||||
* @brief Set the web-server root folder path for all windows. Should be used
|
||||
* before `webui_show()`.
|
||||
*
|
||||
* @param path The local folder full path
|
||||
*
|
||||
@ -280,7 +286,8 @@ WEBUI_EXPORT bool webui_set_default_root_folder(const char* path);
|
||||
* @brief Set a custom handler to serve files.
|
||||
*
|
||||
* @param window The window number
|
||||
* @param handler The handler function: `void myHandler(const char* filename, int* length)`
|
||||
* @param handler The handler function: `void myHandler(const char* filename,
|
||||
* int* length)`
|
||||
*
|
||||
* @return Returns a unique bind ID.
|
||||
*
|
||||
@ -318,7 +325,8 @@ WEBUI_EXPORT void webui_set_timeout(size_t second);
|
||||
WEBUI_EXPORT void webui_set_icon(size_t window, const char* icon, const char* icon_type);
|
||||
|
||||
/**
|
||||
* @brief Base64 encoding. Use this to safely send text based data to the UI. If it fails it will return NULL.
|
||||
* @brief Base64 encoding. Use this to safely send text based data to the UI. If
|
||||
* it fails it will return NULL.
|
||||
*
|
||||
* @param str The string to encode (Should be null terminated)
|
||||
*
|
||||
@ -327,7 +335,8 @@ WEBUI_EXPORT void webui_set_icon(size_t window, const char* icon, const char* ic
|
||||
WEBUI_EXPORT char* webui_encode(const char* str);
|
||||
|
||||
/**
|
||||
* @brief Base64 decoding. Use this to safely decode received Base64 text from the UI. If it fails it will return NULL.
|
||||
* @brief Base64 decoding. Use this to safely decode received Base64 text from
|
||||
* the UI. If it fails it will return NULL.
|
||||
*
|
||||
* @param str The string to decode (Should be null terminated)
|
||||
*
|
||||
@ -345,8 +354,8 @@ WEBUI_EXPORT char* webui_decode(const char* str);
|
||||
WEBUI_EXPORT void webui_free(void* ptr);
|
||||
|
||||
/**
|
||||
* @brief Safely allocate memory using the WebUI memory management system. It can be safely freed using `webui_free()`
|
||||
* at any time.
|
||||
* @brief Safely allocate memory using the WebUI memory management system. It
|
||||
* can be safely freed using `webui_free()` at any time.
|
||||
*
|
||||
* @param size The size of memory in bytes
|
||||
*
|
||||
@ -358,7 +367,8 @@ WEBUI_EXPORT void* webui_malloc(size_t size);
|
||||
* @brief Safely send raw data to the UI.
|
||||
*
|
||||
* @param window The window number
|
||||
* @param function The JavaScript function to receive raw data: `function myFunc(myData){}`
|
||||
* @param function The JavaScript function to receive raw data: `function
|
||||
* myFunc(myData){}`
|
||||
* @param raw The raw data buffer
|
||||
* @param size The raw data size in bytes
|
||||
*
|
||||
@ -399,14 +409,15 @@ WEBUI_EXPORT void webui_set_size(size_t window, unsigned int width, unsigned int
|
||||
WEBUI_EXPORT void webui_set_position(size_t window, unsigned int x, unsigned int y);
|
||||
|
||||
/**
|
||||
* @brief Set the web browser profile to use. An empty `name` and `path` means the default user profile. Need to be
|
||||
* called before `webui_show()`.
|
||||
* @brief Set the web browser profile to use. An empty `name` and `path` means
|
||||
* the default user profile. Need to be called before `webui_show()`.
|
||||
*
|
||||
* @param window The window number
|
||||
* @param name The web browser profile name
|
||||
* @param path The web browser profile full path
|
||||
*
|
||||
* @example webui_set_profile(myWindow, "Bar", "/Home/Foo/Bar"); | webui_set_profile(myWindow, "", "");
|
||||
* @example webui_set_profile(myWindow, "Bar", "/Home/Foo/Bar"); |
|
||||
* webui_set_profile(myWindow, "", "");
|
||||
*/
|
||||
WEBUI_EXPORT void webui_set_profile(size_t window, const char* name, const char* path);
|
||||
|
||||
@ -441,7 +452,8 @@ WEBUI_EXPORT void webui_navigate(size_t window, const char* url);
|
||||
WEBUI_EXPORT void webui_clean();
|
||||
|
||||
/**
|
||||
* @brief Delete all local web-browser profiles folder. It should called at the end.
|
||||
* @brief Delete all local web-browser profiles folder. It should called at the
|
||||
* end.
|
||||
*
|
||||
* @example
|
||||
* webui_wait();
|
||||
@ -460,12 +472,14 @@ WEBUI_EXPORT void webui_delete_all_profiles();
|
||||
* webui_delete_profile(myWindow);
|
||||
* webui_clean();
|
||||
*
|
||||
* @note This can break functionality of other windows if using the same web-browser.
|
||||
* @note This can break functionality of other windows if using the same
|
||||
* web-browser.
|
||||
*/
|
||||
WEBUI_EXPORT void webui_delete_profile(size_t window);
|
||||
|
||||
/**
|
||||
* @brief Get the ID of the parent process (The web browser may re-create another new process).
|
||||
* @brief Get the ID of the parent process (The web browser may re-create
|
||||
* another new process).
|
||||
*
|
||||
* @param window The window number
|
||||
*
|
||||
@ -489,14 +503,17 @@ WEBUI_EXPORT size_t webui_get_child_process_id(size_t window);
|
||||
// -- SSL/TLS -------------------------
|
||||
|
||||
/**
|
||||
* @brief Set the SSL/TLS certificate and the private key content, both in PEM format. This works only with `webui-2-secure` library. If set empty WebUI will generate a self-signed certificate.
|
||||
* @brief Set the SSL/TLS certificate and the private key content, both in PEM
|
||||
* format. This works only with `webui-2-secure` library. If set empty WebUI
|
||||
* will generate a self-signed certificate.
|
||||
*
|
||||
* @param certificate_pem The SSL/TLS certificate content in PEM format
|
||||
* @param private_key_pem The private key content in PEM format
|
||||
*
|
||||
* @return Returns True if the certificate and the key are valid.
|
||||
*
|
||||
* @example bool ret = webui_set_tls_certificate("-----BEGIN CERTIFICATE-----\n...", "-----BEGIN PRIVATE KEY-----\n...");
|
||||
* @example bool ret = webui_set_tls_certificate("-----BEGIN
|
||||
* CERTIFICATE-----\n...", "-----BEGIN PRIVATE KEY-----\n...");
|
||||
*/
|
||||
WEBUI_EXPORT bool webui_set_tls_certificate(const char* certificate_pem, const char* private_key_pem);
|
||||
|
||||
@ -505,7 +522,8 @@ WEBUI_EXPORT bool webui_set_tls_certificate(const char* certificate_pem, const c
|
||||
// Run JavaScript without waiting for the response.
|
||||
WEBUI_EXPORT void webui_run(size_t window, const char* script);
|
||||
|
||||
// Run JavaScript and get the response back (Make sure your local buffer can hold the response).
|
||||
// Run JavaScript and get the response back (Make sure your local buffer can
|
||||
// hold the response).
|
||||
WEBUI_EXPORT bool webui_script(size_t window, const char* script, size_t timeout, char* buffer, size_t buffer_length);
|
||||
|
||||
// Chose between Deno and Nodejs as runtime for .js and .ts files.
|
||||
@ -546,12 +564,14 @@ WEBUI_EXPORT void webui_return_bool(webui_event_t* e, bool b);
|
||||
|
||||
// -- Wrapper's Interface -------------
|
||||
|
||||
// Bind a specific html element click event with a function. Empty element means all events. This replaces
|
||||
// `webui_bind()`. The func is (Window, EventType, Element, EventNumber, BindID).
|
||||
// Bind a specific html element click event with a function. Empty element means
|
||||
// all events. This replaces `webui_bind()`. The func is (Window, EventType,
|
||||
// Element, EventNumber, BindID).
|
||||
WEBUI_EXPORT size_t
|
||||
webui_interface_bind(size_t window, const char* element, void (*func)(size_t, size_t, char*, size_t, size_t));
|
||||
|
||||
// When using `webui_interface_bind()`, you may need this function to easily set your callback response.
|
||||
// When using `webui_interface_bind()`, you may need this function to easily set
|
||||
// your callback response.
|
||||
WEBUI_EXPORT void webui_interface_set_response(size_t window, size_t event_number, const char* response);
|
||||
|
||||
// Check if the app still running.
|
||||
|
521
src/webui.c
521
src/webui.c
@ -345,52 +345,78 @@ static _webui_core_t _webui_core;
|
||||
static const char* webui_html_served =
|
||||
"<html><head><title>Access Denied</title><script "
|
||||
"src=\"/webui.js\"></"
|
||||
"script><style>body{margin:0;background-repeat:no-repeat;background-attachment:fixed;background-color:#FF3CAC;"
|
||||
"script><style>body{margin:0;background-repeat:no-repeat;background-"
|
||||
"attachment:fixed;background-color:#FF3CAC;"
|
||||
"background-image:linear-gradient(225deg,#FF3CAC 0%,#784BA0 45%,#2B86C5 "
|
||||
"100%);font-family:sans-serif;margin:20px;color:#fff}a{color:#fff}</style></head><body><h2>⚠ Access "
|
||||
"Denied</h2><p>You can't access this content<br>because it's already in use in<br>another window.</p><br><a "
|
||||
"100%);font-family:sans-serif;margin:20px;color:#fff}a{color:#fff}</"
|
||||
"style></head><body><h2>⚠ Access "
|
||||
"Denied</h2><p>You can't access this content<br>because it's already in "
|
||||
"use in<br>another window.</p><br><a "
|
||||
"href=\"https://www.webui.me\"><small>WebUI v" WEBUI_VERSION "<small></a></body></html>";
|
||||
static const char* webui_html_res_not_available =
|
||||
"<html><head><title>Resource Not Available</title><script "
|
||||
"src=\"/webui.js\"></"
|
||||
"script><style>body{margin:0;background-repeat:no-repeat;background-attachment:fixed;background-color:#FF3CAC;"
|
||||
"script><style>body{margin:0;background-repeat:no-repeat;background-"
|
||||
"attachment:fixed;background-color:#FF3CAC;"
|
||||
"background-image:linear-gradient(225deg,#FF3CAC 0%,#784BA0 45%,#2B86C5 "
|
||||
"100%);font-family:sans-serif;margin:20px;color:#fff}a{color:#fff}</style></head><body><h2>⚠ Resource Not "
|
||||
"Available</h2><p>The requested resource is not available.</p><br><a href=\"https://www.webui.me\"><small>WebUI "
|
||||
"100%);font-family:sans-serif;margin:20px;color:#fff}a{color:#fff}</"
|
||||
"style></head><body><h2>⚠ Resource Not "
|
||||
"Available</h2><p>The requested resource is not available.</p><br><a "
|
||||
"href=\"https://www.webui.me\"><small>WebUI "
|
||||
"v" WEBUI_VERSION "<small></a></body></html>";
|
||||
static const char* webui_deno_not_found =
|
||||
"<html><head><title>Deno Not Found</title><script "
|
||||
"src=\"/webui.js\"></"
|
||||
"script><style>body{margin:0;background-repeat:no-repeat;background-attachment:fixed;background-color:#FF3CAC;"
|
||||
"script><style>body{margin:0;background-repeat:no-repeat;background-"
|
||||
"attachment:fixed;background-color:#FF3CAC;"
|
||||
"background-image:linear-gradient(225deg,#FF3CAC 0%,#784BA0 45%,#2B86C5 "
|
||||
"100%);font-family:sans-serif;margin:20px;color:#fff}a{color:#fff}</style></head><body><h2>⚠ Deno Not "
|
||||
"Found</h2><p>Deno is not found on this system.<br>Please download it from <a "
|
||||
"href=\"https://github.com/denoland/deno/releases\">https://github.com/denoland/deno/releases</a></p><br><a "
|
||||
"100%);font-family:sans-serif;margin:20px;color:#fff}a{color:#fff}</"
|
||||
"style></head><body><h2>⚠ Deno Not "
|
||||
"Found</h2><p>Deno is not found on this system.<br>Please download it from "
|
||||
"<a "
|
||||
"href=\"https://github.com/denoland/deno/releases\">https://github.com/"
|
||||
"denoland/deno/releases</a></p><br><a "
|
||||
"href=\"https://www.webui.me\"><small>WebUI v" WEBUI_VERSION "<small></a></body></html>";
|
||||
static const char* webui_nodejs_not_found =
|
||||
"<html><head><title>Node.js Not Found</title><script "
|
||||
"src=\"/webui.js\"></"
|
||||
"script><style>body{margin:0;background-repeat:no-repeat;background-attachment:fixed;background-color:#FF3CAC;"
|
||||
"script><style>body{margin:0;background-repeat:no-repeat;background-"
|
||||
"attachment:fixed;background-color:#FF3CAC;"
|
||||
"background-image:linear-gradient(225deg,#FF3CAC 0%,#784BA0 45%,#2B86C5 "
|
||||
"100%);font-family:sans-serif;margin:20px;color:#fff}a{color:#fff}</style></head><body><h2>⚠ Node.js Not "
|
||||
"Found</h2><p>Node.js is not found on this system.<br>Please download it from <a "
|
||||
"href=\"https://nodejs.org/en/download/\">https://nodejs.org/en/download/</a></p><br><a "
|
||||
"100%);font-family:sans-serif;margin:20px;color:#fff}a{color:#fff}</"
|
||||
"style></head><body><h2>⚠ Node.js Not "
|
||||
"Found</h2><p>Node.js is not found on this system.<br>Please download it "
|
||||
"from <a "
|
||||
"href=\"https://nodejs.org/en/download/\">https://nodejs.org/en/download/</"
|
||||
"a></p><br><a "
|
||||
"href=\"https://www.webui.me\"><small>WebUI v" WEBUI_VERSION "<small></a></body></html>";
|
||||
static const char* webui_def_icon =
|
||||
"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"64\" height=\"64\" viewBox=\"0 0 64 64\" version=\"1.1\"><path "
|
||||
"d=\"M 35.315 15.983 C 30.885 17.816, 29.305 25.835, 33.500 25.195 C 34.600 25.027, 37.177 24.802, 39.227 24.695 C "
|
||||
"44.084 24.441, 49.054 19.899, 47.386 17.239 C 46.146 15.262, 38.884 14.507, 35.315 15.983 M 54.602 17.835 C "
|
||||
"54.058 18.716, 60.204 22.022, 62.284 21.968 C 63.958 21.925, 58.228 17, 56.503 17 C 55.741 17, 54.886 17.376, "
|
||||
"54.602 17.835\" stroke=\"none\" fill=\"#789dcc\" fill-rule=\"evenodd\"/><path d=\"M 3.635 19.073 C 2.098 20.282, "
|
||||
"1 22.144, 1 23.542 C 1 26.692, 12.655 53.139, 14.754 54.750 C 15.650 55.437, 17.882 56, 19.716 56 C 23.227 56, "
|
||||
"22.667 56.645, 30.331 43.762 L 32.163 40.684 36.109 47.830 C 40.333 55.479, 42.889 57.131, 47.815 55.394 C 49.855 "
|
||||
"54.675, 51.575 51.765, 56.620 40.500 C 60.068 32.800, 62.904 25.600, 62.921 24.500 C 62.944 23.042, 61.572 "
|
||||
"21.893, 57.862 20.262 C 55.062 19.031, 52.336 18.292, 51.806 18.620 C 51.275 18.948, 49.385 22.428, 47.604 26.353 "
|
||||
"L 44.367 33.490 42.504 30.647 C 41.121 28.536, 40.907 27.379, 41.673 26.152 C 42.567 24.721, 42.224 24.526, "
|
||||
"39.103 24.695 C 37.121 24.802, 34.600 25.027, 33.500 25.195 C 31.780 25.457, 31.517 24.966, 31.620 21.688 L "
|
||||
"31.739 17.876 28.799 20.688 C 27.182 22.235, 24.694 25.637, 23.270 28.250 C 21.847 30.863, 20.354 33, 19.954 33 C "
|
||||
"19.553 33, 17.969 30.044, 16.433 26.431 C 12.452 17.064, 8.833 14.984, 3.635 19.073\" stroke=\"none\" "
|
||||
"fill=\"#294fb7\" fill-rule=\"evenodd\"/></svg>";
|
||||
static const char* webui_def_icon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"64\" height=\"64\" "
|
||||
"viewBox=\"0 0 64 64\" version=\"1.1\"><path "
|
||||
"d=\"M 35.315 15.983 C 30.885 17.816, 29.305 25.835, 33.500 25.195 C "
|
||||
"34.600 25.027, 37.177 24.802, 39.227 24.695 C "
|
||||
"44.084 24.441, 49.054 19.899, 47.386 17.239 C 46.146 15.262, 38.884 "
|
||||
"14.507, 35.315 15.983 M 54.602 17.835 C "
|
||||
"54.058 18.716, 60.204 22.022, 62.284 21.968 C 63.958 21.925, 58.228 17, "
|
||||
"56.503 17 C 55.741 17, 54.886 17.376, "
|
||||
"54.602 17.835\" stroke=\"none\" fill=\"#789dcc\" "
|
||||
"fill-rule=\"evenodd\"/><path d=\"M 3.635 19.073 C 2.098 20.282, "
|
||||
"1 22.144, 1 23.542 C 1 26.692, 12.655 53.139, 14.754 54.750 C 15.650 "
|
||||
"55.437, 17.882 56, 19.716 56 C 23.227 56, "
|
||||
"22.667 56.645, 30.331 43.762 L 32.163 40.684 36.109 47.830 C 40.333 "
|
||||
"55.479, 42.889 57.131, 47.815 55.394 C 49.855 "
|
||||
"54.675, 51.575 51.765, 56.620 40.500 C 60.068 32.800, 62.904 25.600, "
|
||||
"62.921 24.500 C 62.944 23.042, 61.572 "
|
||||
"21.893, 57.862 20.262 C 55.062 19.031, 52.336 18.292, 51.806 18.620 C "
|
||||
"51.275 18.948, 49.385 22.428, 47.604 26.353 "
|
||||
"L 44.367 33.490 42.504 30.647 C 41.121 28.536, 40.907 27.379, 41.673 "
|
||||
"26.152 C 42.567 24.721, 42.224 24.526, "
|
||||
"39.103 24.695 C 37.121 24.802, 34.600 25.027, 33.500 25.195 C 31.780 "
|
||||
"25.457, 31.517 24.966, 31.620 21.688 L "
|
||||
"31.739 17.876 28.799 20.688 C 27.182 22.235, 24.694 25.637, 23.270 28.250 "
|
||||
"C 21.847 30.863, 20.354 33, 19.954 33 C "
|
||||
"19.553 33, 17.969 30.044, 16.433 26.431 C 12.452 17.064, 8.833 14.984, "
|
||||
"3.635 19.073\" stroke=\"none\" "
|
||||
"fill=\"#294fb7\" fill-rule=\"evenodd\"/></svg>";
|
||||
static const char* webui_def_icon_type = "image/svg+xml";
|
||||
|
||||
// -- Functions -----------------------
|
||||
@ -1465,7 +1491,8 @@ static bool _webui_check_certificate(const char* certificate_pem, const char* pr
|
||||
// Use certificate
|
||||
if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_check_certificate() -> SSL_CTX_use_certificate failed\n");
|
||||
printf("[Core]\t\t_webui_check_certificate() -> SSL_CTX_use_certificate "
|
||||
"failed\n");
|
||||
#endif
|
||||
BIO_free_all(bio_cert);
|
||||
X509_free(cert);
|
||||
@ -1478,7 +1505,8 @@ static bool _webui_check_certificate(const char* certificate_pem, const char* pr
|
||||
EVP_PKEY* private_key = PEM_read_bio_PrivateKey(bio_key, NULL, 0, NULL);
|
||||
if (private_key == NULL) {
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_check_certificate() -> PEM_read_bio_PrivateKey failed\n");
|
||||
printf("[Core]\t\t_webui_check_certificate() -> PEM_read_bio_PrivateKey "
|
||||
"failed\n");
|
||||
#endif
|
||||
EVP_PKEY_free(private_key);
|
||||
BIO_free_all(bio_key);
|
||||
@ -1492,7 +1520,8 @@ static bool _webui_check_certificate(const char* certificate_pem, const char* pr
|
||||
// Use key
|
||||
if (SSL_CTX_use_PrivateKey(ctx, private_key) <= 0) {
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_check_certificate() -> SSL_CTX_use_PrivateKey failed\n");
|
||||
printf("[Core]\t\t_webui_check_certificate() -> SSL_CTX_use_PrivateKey "
|
||||
"failed\n");
|
||||
#endif
|
||||
EVP_PKEY_free(private_key);
|
||||
BIO_free_all(bio_key);
|
||||
@ -1604,7 +1633,8 @@ size_t webui_get_child_process_id(size_t window) {
|
||||
if (!dir)
|
||||
return win->process_id;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
// Ensure we're looking at a process directory (directories that are just numbers)
|
||||
// Ensure we're looking at a process directory (directories that are just
|
||||
// numbers)
|
||||
if (entry->d_type == DT_DIR && strspn(entry->d_name, "0123456789") == strlen(entry->d_name)) {
|
||||
char statFilepath[1024];
|
||||
snprintf(statFilepath, sizeof(statFilepath), "/proc/%s/stat", entry->d_name);
|
||||
@ -2199,7 +2229,8 @@ static void _webui_interface_bind_handler(webui_event_t* e) {
|
||||
|
||||
// Call cb
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_interface_bind_handler() -> Calling user callback...\n[Call]\n");
|
||||
printf("[Core]\t\t_webui_interface_bind_handler() -> Calling user "
|
||||
"callback...\n[Call]\n");
|
||||
#endif
|
||||
_webui_core.cb_interface[cb_index](e->window, e->event_type, e->element, e->event_number, e->bind_id);
|
||||
}
|
||||
@ -2219,7 +2250,11 @@ static void _webui_interface_bind_handler(webui_event_t* e) {
|
||||
response = event_inf->response;
|
||||
}
|
||||
|
||||
printf("[Core]\t\t_webui_interface_bind_handler() -> user-callback response [%s]\n", response);
|
||||
printf(
|
||||
"[Core]\t\t_webui_interface_bind_handler() -> user-callback response "
|
||||
"[%s]\n",
|
||||
response
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2403,7 +2438,8 @@ static void _webui_ptr_add(void* ptr, size_t size) {
|
||||
if (_webui_core.ptr_list[i] == NULL) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
// printf("[Core]\t\t_webui_ptr_add(0x%p) -> Allocate %zu bytes\n", ptr, size);
|
||||
// printf("[Core]\t\t_webui_ptr_add(0x%p) -> Allocate %zu bytes\n", ptr,
|
||||
// size);
|
||||
#endif
|
||||
|
||||
_webui_core.ptr_list[i] = ptr;
|
||||
@ -2413,7 +2449,8 @@ static void _webui_ptr_add(void* ptr, size_t size) {
|
||||
}
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
// printf("[Core]\t\t_webui_ptr_add(0x%p) -> Allocate %zu bytes\n", ptr, size);
|
||||
// printf("[Core]\t\t_webui_ptr_add(0x%p) -> Allocate %zu bytes\n", ptr,
|
||||
// size);
|
||||
#endif
|
||||
|
||||
_webui_core.ptr_list[_webui_core.ptr_position] = ptr;
|
||||
@ -3228,14 +3265,16 @@ static int _webui_interpret_file(_webui_window_t* win, struct mg_connection* con
|
||||
#ifdef _WIN32
|
||||
sprintf(
|
||||
cmd,
|
||||
"Set NO_COLOR=1 & Set DENO_NO_UPDATE_CHECK=1 & deno run --quiet --allow-all "
|
||||
"Set NO_COLOR=1 & Set DENO_NO_UPDATE_CHECK=1 & deno run "
|
||||
"--quiet --allow-all "
|
||||
"--unstable \"%s\" \"%s\"",
|
||||
full_path, query
|
||||
);
|
||||
#else
|
||||
sprintf(
|
||||
cmd,
|
||||
"NO_COLOR=1; DENO_NO_UPDATE_CHECK=1; deno run --quiet --allow-all --unstable "
|
||||
"NO_COLOR=1; DENO_NO_UPDATE_CHECK=1; deno run --quiet "
|
||||
"--allow-all --unstable "
|
||||
"\"%s\" \"%s\"",
|
||||
full_path, query
|
||||
);
|
||||
@ -3343,7 +3382,8 @@ static const char* _webui_generate_js_bridge(_webui_window_t* win) {
|
||||
#ifdef WEBUI_LOG
|
||||
// Non-authorized connection
|
||||
else
|
||||
printf("[Core]\t\t_webui_generate_js_bridge() -> Non-authorized connection.\n");
|
||||
printf("[Core]\t\t_webui_generate_js_bridge() -> Non-authorized "
|
||||
"connection.\n");
|
||||
#endif
|
||||
|
||||
if (token == 0) {
|
||||
@ -3387,7 +3427,8 @@ static const char* _webui_generate_js_bridge(_webui_window_t* win) {
|
||||
char* js = (char*)_webui_malloc(len);
|
||||
int c = sprintf(
|
||||
js,
|
||||
"%s\n document.addEventListener(\"DOMContentLoaded\",function(){ globalThis.webui = new WebuiBridge({ "
|
||||
"%s\n document.addEventListener(\"DOMContentLoaded\",function(){ "
|
||||
"globalThis.webui = new WebuiBridge({ "
|
||||
"secure: %s, token: %" PRIu32 ", port: %zu, winNum: %zu, bindList: %s, log: %s, ",
|
||||
webui_javascript_bridge,
|
||||
#ifdef WEBUI_TLS
|
||||
@ -3441,7 +3482,11 @@ static bool _webui_browser_create_new_profile(_webui_window_t* win, size_t brows
|
||||
}
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_browser_create_new_profile(%zu) -> Generating WebUI profile...\n", browser);
|
||||
printf(
|
||||
"[Core]\t\t_webui_browser_create_new_profile(%zu) -> Generating WebUI "
|
||||
"profile...\n",
|
||||
browser
|
||||
);
|
||||
#endif
|
||||
|
||||
// Temp folder
|
||||
@ -3551,7 +3596,11 @@ static bool _webui_browser_create_new_profile(_webui_window_t* win, size_t brows
|
||||
file = fopen(buf, "a");
|
||||
if (file == NULL)
|
||||
return false;
|
||||
fputs("user_pref(\"toolkit.legacyUserProfileCustomizations.stylesheets\", true); ", file);
|
||||
fputs(
|
||||
"user_pref(\"toolkit.legacyUserProfileCustomizations.stylesheets\","
|
||||
" true); ",
|
||||
file
|
||||
);
|
||||
fputs("user_pref(\"browser.shell.checkDefaultBrowser\", false); ", file);
|
||||
fputs("user_pref(\"browser.tabs.warnOnClose\", false); ", file);
|
||||
fclose(file);
|
||||
@ -3570,60 +3619,94 @@ static bool _webui_browser_create_new_profile(_webui_window_t* win, size_t brows
|
||||
#ifdef _WIN32
|
||||
fputs(
|
||||
":root{--uc-toolbar-height:32px}:root:not([uidensity=\"compact\"]) "
|
||||
"{--uc-toolbar-height:38px}#TabsToolbar{visibility:collapse!important}:root:not(["
|
||||
"{--uc-toolbar-height:38px}#TabsToolbar{visibility:collapse!"
|
||||
"important}:root:not(["
|
||||
"inFullscreen]) #nav-bar{margin-top:calc(0px - "
|
||||
"var(--uc-toolbar-height))}#toolbar-menubar{min-height:unset!important;height:var(--uc-"
|
||||
"toolbar-height)!important;position:relative}#main-menubar{-moz-box-flex:1;background-"
|
||||
"color:var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor);background-clip:padding-box;border-"
|
||||
"var(--uc-toolbar-height))}#toolbar-menubar{min-height:unset!"
|
||||
"important;height:var(--uc-"
|
||||
"toolbar-height)!important;position:relative}#main-menubar{-moz-"
|
||||
"box-flex:1;background-"
|
||||
"color:var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor);background-"
|
||||
"clip:padding-box;border-"
|
||||
"right:30px solid transparent;border-image:linear-gradient(to "
|
||||
"left,transparent,var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor) 30px) 20 / "
|
||||
"30px}#toolbar-menubar:not([inactive]) {z-index:2}#toolbar-menubar[inactive] > "
|
||||
"#menubar-items{opacity:0;pointer-events:none;margin-left:var(--uc-window-drag-space-width,"
|
||||
"left,transparent,var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor) "
|
||||
"30px) 20 / "
|
||||
"30px}#toolbar-menubar:not([inactive]) "
|
||||
"{z-index:2}#toolbar-menubar[inactive] > "
|
||||
"#menubar-items{opacity:0;pointer-events:none;margin-left:var(--uc-"
|
||||
"window-drag-space-width,"
|
||||
"0px)}#nav-bar{visibility:collapse}@-moz-document "
|
||||
"url(chrome://browser/content/browser.xhtml) {:root:not([sizemode=\"fullscreen\"]) > "
|
||||
"head{display: block;position: fixed;width: calc(200vw - 440px);text-align: left;z-index: "
|
||||
"9;pointer-events: none;}head > *{ display: none }head > title{display: "
|
||||
"-moz-inline-box;padding: 4px;max-width: 50vw;overflow-x: hidden;text-overflow: "
|
||||
"url(chrome://browser/content/browser.xhtml) "
|
||||
"{:root:not([sizemode=\"fullscreen\"]) > "
|
||||
"head{display: block;position: fixed;width: calc(200vw - "
|
||||
"440px);text-align: left;z-index: "
|
||||
"9;pointer-events: none;}head > *{ display: none }head > "
|
||||
"title{display: "
|
||||
"-moz-inline-box;padding: 4px;max-width: 50vw;overflow-x: "
|
||||
"hidden;text-overflow: "
|
||||
"ellipsis;}}",
|
||||
file
|
||||
);
|
||||
#elif __APPLE__
|
||||
fputs(
|
||||
// ":root{--uc-toolbar-height:32px}:root:not([uidensity=\"compact\"]) "
|
||||
// "{--uc-toolbar-height:38px}#TabsToolbar{visibility:collapse!important} "
|
||||
// ":root{--uc-toolbar-height:32px}:root:not([uidensity=\"compact\"])
|
||||
// "
|
||||
// "{--uc-toolbar-height:38px}#TabsToolbar{visibility:collapse!important}
|
||||
// "
|
||||
":root:not([inFullscreen]) #nav-bar{margin-top:calc(0px - "
|
||||
"var(--uc-toolbar-height))}#toolbar-menubar{min-height:unset!important;height:var(--uc-"
|
||||
"toolbar-height)!important;position:relative}#main-menubar{-moz-box-flex:1;background-"
|
||||
"color:var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor);background-clip:padding-box;border-"
|
||||
"var(--uc-toolbar-height))}#toolbar-menubar{min-height:unset!"
|
||||
"important;height:var(--uc-"
|
||||
"toolbar-height)!important;position:relative}#main-menubar{-moz-box-"
|
||||
"flex:1;background-"
|
||||
"color:var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor);background-"
|
||||
"clip:padding-box;border-"
|
||||
"right:30px solid transparent;border-image:linear-gradient(to "
|
||||
"left,transparent,var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor) 30px) 20 / "
|
||||
"30px}#toolbar-menubar:not([inactive]) {z-index:2}#toolbar-menubar[inactive] > "
|
||||
"#menubar-items{opacity:0;pointer-events:none;margin-left:var(--uc-window-drag-space-width,"
|
||||
"left,transparent,var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor) "
|
||||
"30px) 20 / "
|
||||
"30px}#toolbar-menubar:not([inactive]) "
|
||||
"{z-index:2}#toolbar-menubar[inactive] > "
|
||||
"#menubar-items{opacity:0;pointer-events:none;margin-left:var(--uc-"
|
||||
"window-drag-space-width,"
|
||||
"0px)}#nav-bar{visibility:collapse}@-moz-document "
|
||||
"url(chrome://browser/content/browser.xhtml) {:root:not([sizemode=\"fullscreen\"]) > "
|
||||
"head{display: block;position: fixed;width: calc(200vw - 440px);text-align: left;z-index: "
|
||||
"9;pointer-events: none;}head > *{ display: none }head > title{display: "
|
||||
"-moz-inline-box;padding: 4px;max-width: 50vw;overflow-x: hidden;text-overflow: "
|
||||
"url(chrome://browser/content/browser.xhtml) "
|
||||
"{:root:not([sizemode=\"fullscreen\"]) > "
|
||||
"head{display: block;position: fixed;width: calc(200vw - "
|
||||
"440px);text-align: left;z-index: "
|
||||
"9;pointer-events: none;}head > *{ display: none }head > "
|
||||
"title{display: "
|
||||
"-moz-inline-box;padding: 4px;max-width: 50vw;overflow-x: "
|
||||
"hidden;text-overflow: "
|
||||
"ellipsis;}}",
|
||||
file
|
||||
);
|
||||
#else
|
||||
fputs(
|
||||
":root{--uc-toolbar-height:32px}:root:not([uidensity=\"compact\"]) "
|
||||
"{--uc-toolbar-height:38px}#TabsToolbar{visibility:collapse!important}:root:not(["
|
||||
"{--uc-toolbar-height:38px}#TabsToolbar{visibility:collapse!"
|
||||
"important}:root:not(["
|
||||
"inFullscreen]) #nav-bar{margin-top:calc(0px - "
|
||||
"var(--uc-toolbar-height))}#toolbar-menubar{min-height:unset!important;height:var(--uc-"
|
||||
"toolbar-height)!important;position:relative}#main-menubar{-moz-box-flex:1;background-"
|
||||
"color:var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor);background-clip:padding-box;border-"
|
||||
"var(--uc-toolbar-height))}#toolbar-menubar{min-height:unset!"
|
||||
"important;height:var(--uc-"
|
||||
"toolbar-height)!important;position:relative}#main-menubar{-moz-"
|
||||
"box-flex:1;background-"
|
||||
"color:var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor);background-"
|
||||
"clip:padding-box;border-"
|
||||
"right:30px solid transparent;border-image:linear-gradient(to "
|
||||
"left,transparent,var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor) 30px) 20 / "
|
||||
"30px}#toolbar-menubar:not([inactive]) {z-index:2}#toolbar-menubar[inactive] > "
|
||||
"#menubar-items{opacity:0;pointer-events:none;margin-left:var(--uc-window-drag-space-width,"
|
||||
"left,transparent,var(--toolbar-bgcolor,--toolbar-non-lwt-bgcolor) "
|
||||
"30px) 20 / "
|
||||
"30px}#toolbar-menubar:not([inactive]) "
|
||||
"{z-index:2}#toolbar-menubar[inactive] > "
|
||||
"#menubar-items{opacity:0;pointer-events:none;margin-left:var(--uc-"
|
||||
"window-drag-space-width,"
|
||||
"0px)}#nav-bar{visibility:collapse}@-moz-document "
|
||||
"url(chrome://browser/content/browser.xhtml) {:root:not([sizemode=\"fullscreen\"]) > "
|
||||
"head{display: block;position: fixed;width: calc(200vw - 440px);text-align: left;z-index: "
|
||||
"9;pointer-events: none;}head > *{ display: none }head > title{display: "
|
||||
"-moz-inline-box;padding: 4px;max-width: 50vw;overflow-x: hidden;text-overflow: "
|
||||
"url(chrome://browser/content/browser.xhtml) "
|
||||
"{:root:not([sizemode=\"fullscreen\"]) > "
|
||||
"head{display: block;position: fixed;width: calc(200vw - "
|
||||
"440px);text-align: left;z-index: "
|
||||
"9;pointer-events: none;}head > *{ display: none }head > "
|
||||
"title{display: "
|
||||
"-moz-inline-box;padding: 4px;max-width: 50vw;overflow-x: "
|
||||
"hidden;text-overflow: "
|
||||
"ellipsis;}}",
|
||||
file
|
||||
);
|
||||
@ -3906,9 +3989,12 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
char browser_folder[WEBUI_MAX_PATH];
|
||||
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Google Chrome installed for multi-user)
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Google Chrome installed for
|
||||
// multi-user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe",
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\chrome.exe",
|
||||
L"Path", browser_folder
|
||||
)) {
|
||||
|
||||
@ -3924,7 +4010,9 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_CURRENT_USER` (If Google Chrome installed for one user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe",
|
||||
HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\chrome.exe",
|
||||
L"Path", browser_folder
|
||||
)) {
|
||||
|
||||
@ -3983,8 +4071,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Edge installed for multi-user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\msedge.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\msedge.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -3999,8 +4089,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_CURRENT_USER` (If Edge installed for one user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\msedge.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\msedge.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -4064,8 +4156,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_CURRENT_USER` (If Epic installed for one user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\epic.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\epic.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -4080,8 +4174,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Epic installed for multi-user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\epic.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\epic.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -4133,7 +4229,9 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Vivaldi installed for multi-user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\vivaldi.exe",
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\vivaldi.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
@ -4149,8 +4247,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_CURRENT_USER` (If Vivaldi installed for one user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\vivaldi.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\vivaldi.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -4212,8 +4312,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Brave installed for multi-user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\brave.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\brave.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -4228,8 +4330,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_CURRENT_USER` (If Brave installed for one user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\brave.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\brave.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -4281,7 +4385,9 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Firefox installed for multi-user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\firefox.exe",
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\firefox.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
@ -4297,8 +4403,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_CURRENT_USER` (If Firefox installed for one user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\firefox.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\firefox.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -4353,8 +4461,10 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_CURRENT_USER` (If Yandex installed for one user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\browser.exe", L"",
|
||||
browser_fullpath
|
||||
HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\browser.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
// Make sure the browser executable file exist
|
||||
@ -4369,7 +4479,9 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Yandex installed for multi-user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\browser.exe",
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\browser.exe",
|
||||
L"", browser_fullpath
|
||||
)) {
|
||||
|
||||
@ -4422,7 +4534,9 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_CURRENT_USER` (If Chromium installed for one user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe",
|
||||
HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\chrome.exe",
|
||||
L"Path", browser_folder
|
||||
)) {
|
||||
|
||||
@ -4438,7 +4552,9 @@ static bool _webui_browser_exist(_webui_window_t* win, size_t browser) {
|
||||
|
||||
// Search in `HKEY_LOCAL_MACHINE` (If Chromium installed for multi-user)
|
||||
if (_webui_get_windows_reg_value(
|
||||
HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe",
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVer"
|
||||
L"sion\\App Paths\\chrome.exe",
|
||||
L"Path", browser_folder
|
||||
)) {
|
||||
|
||||
@ -4964,7 +5080,8 @@ static bool _webui_browser_start(_webui_window_t* win, const char* address, size
|
||||
// #5 - Brave - Shows a policy notification in the first run
|
||||
// #6 - Firefox - Does not support App-Mode like Chrome (Looks not great)
|
||||
// #7 - Yandex - Shows a big welcome window in the first run
|
||||
// #8 - Chromium - Some Anti-Malware shows a false alert when using ungoogled-chromium-binaries
|
||||
// #8 - Chromium - Some Anti-Malware shows a false alert when using
|
||||
// ungoogled-chromium-binaries
|
||||
|
||||
if (browser != AnyBrowser) {
|
||||
|
||||
@ -5172,7 +5289,8 @@ static size_t _webui_find_the_best_browser(_webui_window_t* win) {
|
||||
// #5 - Brave - Shows a policy notification in the first run
|
||||
// #6 - Firefox - Does not support App-Mode like Chrome (Looks not great)
|
||||
// #7 - Yandex - Shows a big welcome window in the first run
|
||||
// #8 - Chromium - Some Anti-Malware shows a false alert when using ungoogled-chromium-binaries
|
||||
// #8 - Chromium - Some Anti-Malware shows a false alert when using
|
||||
// ungoogled-chromium-binaries
|
||||
|
||||
// To save memory, let's search if a web browser is already running
|
||||
|
||||
@ -5303,7 +5421,8 @@ static int _webui_tls_initialization(void* ssl_ctx, void* ptr) {
|
||||
}
|
||||
if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_tls_initialization() -> SSL_CTX_use_certificate failed\n");
|
||||
printf("[Core]\t\t_webui_tls_initialization() -> SSL_CTX_use_certificate "
|
||||
"failed\n");
|
||||
#endif
|
||||
_webui_panic();
|
||||
return -1;
|
||||
@ -5316,14 +5435,16 @@ static int _webui_tls_initialization(void* ssl_ctx, void* ptr) {
|
||||
EVP_PKEY* private_key = PEM_read_bio_PrivateKey(bio_key, NULL, 0, NULL);
|
||||
if (private_key == NULL) {
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_tls_initialization() -> PEM_read_bio_PrivateKey failed\n");
|
||||
printf("[Core]\t\t_webui_tls_initialization() -> PEM_read_bio_PrivateKey "
|
||||
"failed\n");
|
||||
#endif
|
||||
_webui_panic();
|
||||
return -1;
|
||||
}
|
||||
if (SSL_CTX_use_PrivateKey(ctx, private_key) <= 0) {
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_tls_initialization() -> SSL_CTX_use_PrivateKey failed\n");
|
||||
printf("[Core]\t\t_webui_tls_initialization() -> SSL_CTX_use_PrivateKey "
|
||||
"failed\n");
|
||||
#endif
|
||||
_webui_panic();
|
||||
return -1;
|
||||
@ -5364,15 +5485,21 @@ static bool _webui_tls_generate_self_signed_cert(char* root_cert, char* root_key
|
||||
X509_gmtime_adj(X509_get_notAfter(root_x509), (long)(WEBUI_SSL_EXPIRE));
|
||||
|
||||
X509_NAME* root_name = X509_get_subject_name(root_x509);
|
||||
X509_NAME_add_entry_by_txt(root_name, "C", MBSTRING_ASC, "CA", -1, -1, 0); // Country
|
||||
X509_NAME_add_entry_by_txt(root_name, "C", MBSTRING_ASC, "CA", -1, -1,
|
||||
0); // Country
|
||||
X509_NAME_add_entry_by_txt(root_name, "O", MBSTRING_ASC, "WebUI Root Authority", -1, -1, 0); // Organization
|
||||
X509_NAME_add_entry_by_txt(root_name, "OU", MBSTRING_ASC, "WebUI", -1, -1, 0); // Organizational Unit
|
||||
X509_NAME_add_entry_by_txt(root_name, "CN", MBSTRING_ASC, "localhost", -1, -1, 0); // Common Name
|
||||
X509_NAME_add_entry_by_txt(root_name, "OU", MBSTRING_ASC, "WebUI", -1, -1,
|
||||
0); // Organizational Unit
|
||||
X509_NAME_add_entry_by_txt(root_name, "CN", MBSTRING_ASC, "localhost", -1, -1,
|
||||
0); // Common Name
|
||||
X509_NAME_add_entry_by_txt(
|
||||
root_name, "subjectAltName", MBSTRING_ASC, "127.0.0.1", -1, -1, 0
|
||||
); // Subject Alternative Name
|
||||
X509_NAME_add_entry_by_txt(root_name, "ST", MBSTRING_ASC, "WebUI", -1, -1, 0); // State
|
||||
X509_NAME_add_entry_by_txt(root_name, "L", MBSTRING_ASC, "WebUI", -1, -1, 0); // Locality
|
||||
root_name, "subjectAltName", MBSTRING_ASC, "127.0.0.1", -1, -1,
|
||||
0
|
||||
); // Subject Alternative Name
|
||||
X509_NAME_add_entry_by_txt(root_name, "ST", MBSTRING_ASC, "WebUI", -1, -1,
|
||||
0); // State
|
||||
X509_NAME_add_entry_by_txt(root_name, "L", MBSTRING_ASC, "WebUI", -1, -1,
|
||||
0); // Locality
|
||||
|
||||
X509_set_issuer_name(root_x509, root_name);
|
||||
X509_set_pubkey(root_x509, root_pkey);
|
||||
@ -5420,15 +5547,21 @@ static bool _webui_tls_generate_self_signed_cert(char* root_cert, char* root_key
|
||||
X509_gmtime_adj(X509_get_notAfter(x509), (long)(WEBUI_SSL_EXPIRE));
|
||||
|
||||
X509_NAME* name = X509_get_subject_name(x509);
|
||||
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, "CA", -1, -1, 0); // Country
|
||||
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, "WebUI", -1, -1, 0); // Organization
|
||||
X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, "WebUI", -1, -1, 0); // Organizational Unit
|
||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, "localhost", -1, -1, 0); // Common Name
|
||||
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, "CA", -1, -1,
|
||||
0); // Country
|
||||
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, "WebUI", -1, -1,
|
||||
0); // Organization
|
||||
X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, "WebUI", -1, -1,
|
||||
0); // Organizational Unit
|
||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, "localhost", -1, -1,
|
||||
0); // Common Name
|
||||
X509_NAME_add_entry_by_txt(
|
||||
name, "subjectAltName", MBSTRING_ASC, "127.0.0.1", -1, -1, 0
|
||||
); // Subject Alternative Name
|
||||
X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, "WebUI", -1, -1, 0); // State
|
||||
X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, "WebUI", -1, -1, 0); // Locality
|
||||
); // Subject Alternative Name
|
||||
X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, "WebUI", -1, -1,
|
||||
0); // State
|
||||
X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, "WebUI", -1, -1,
|
||||
0); // Locality
|
||||
|
||||
X509_set_issuer_name(x509, root_name);
|
||||
X509_set_pubkey(x509, pkey);
|
||||
@ -5480,7 +5613,8 @@ static bool _webui_show_window(_webui_window_t* win, const char* content, bool i
|
||||
if (_webui_is_empty(_webui_core.ssl_cert) || _webui_is_empty(_webui_core.ssl_key)) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_show_window() -> Generating self-signed TLS certificate...\n");
|
||||
printf("[Core]\t\t_webui_show_window() -> Generating self-signed TLS "
|
||||
"certificate...\n");
|
||||
#endif
|
||||
|
||||
// Generate SSL self-signed certificate
|
||||
@ -5494,7 +5628,8 @@ static bool _webui_show_window(_webui_window_t* win, const char* content, bool i
|
||||
char err_buf[1024];
|
||||
ERR_error_string_n(err, err_buf, sizeof(err_buf));
|
||||
printf(
|
||||
"[Core]\t\t_webui_show_window() -> Generating self-signed TLS certificate failed:\n%s\n",
|
||||
"[Core]\t\t_webui_show_window() -> Generating self-signed TLS "
|
||||
"certificate failed:\n%s\n",
|
||||
err_buf
|
||||
);
|
||||
#endif
|
||||
@ -5512,7 +5647,8 @@ static bool _webui_show_window(_webui_window_t* win, const char* content, bool i
|
||||
_webui_core.ssl_key = ssl_key;
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_show_window() -> Self-signed SSL/TLS Certificate:\nRoot:\n");
|
||||
printf("[Core]\t\t_webui_show_window() -> Self-signed SSL/TLS "
|
||||
"Certificate:\nRoot:\n");
|
||||
printf("%s\n", (const char*)_webui_core.root_cert);
|
||||
printf("%s\nServer:\n", (const char*)_webui_core.root_key);
|
||||
printf("%s\n", (const char*)_webui_core.ssl_cert);
|
||||
@ -5642,7 +5778,8 @@ static void _webui_window_event(
|
||||
|
||||
// Call user all-events cb
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_window_event() -> Calling all-events user callback...\n[Call]\n");
|
||||
printf("[Core]\t\t_webui_window_event() -> Calling all-events user "
|
||||
"callback...\n[Call]\n");
|
||||
#endif
|
||||
e.bind_id = events_cb_index;
|
||||
_webui_core.cb[events_cb_index](&e);
|
||||
@ -5659,7 +5796,8 @@ static void _webui_window_event(
|
||||
|
||||
// Call user cb
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_window_event() -> Calling user callback...\n[Call]\n");
|
||||
printf("[Core]\t\t_webui_window_event() -> Calling user "
|
||||
"callback...\n[Call]\n");
|
||||
#endif
|
||||
e.bind_id = cb_index;
|
||||
_webui_core.cb[cb_index](&e);
|
||||
@ -5968,7 +6106,8 @@ static int _webui_http_log(const struct mg_connection* conn, const char* message
|
||||
#endif
|
||||
|
||||
/*
|
||||
static char* _webui_inject_bridge(_webui_window_t* win, const char *user_html) {
|
||||
static char* _webui_inject_bridge(_webui_window_t* win, const char
|
||||
*user_html) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_inject_bridge()...\n");
|
||||
@ -6000,8 +6139,8 @@ static int _webui_http_log(const struct mg_connection* conn, const char* message
|
||||
size_t len = _webui_strlen(user_html) + 128;
|
||||
char* buffer = (char*) _webui_malloc(len);
|
||||
sprintf(buffer,
|
||||
"<html> <script type=\"application/javascript\" src=\"webui.js\"></script>\n %s",
|
||||
user_html
|
||||
"<html> <script type=\"application/javascript\"
|
||||
src=\"webui.js\"></script>\n %s", user_html
|
||||
);
|
||||
return buffer;
|
||||
}
|
||||
@ -6015,8 +6154,9 @@ static int _webui_http_log(const struct mg_connection* conn, const char* message
|
||||
int offset = (int)(head_pos - user_html) + 6;
|
||||
|
||||
// Calculate the length for the new string
|
||||
const char* script = "<script type=\"application/javascript\" src=\"webui.js\"></script> \n";
|
||||
size_t new_len = strlen(user_html) + strlen(script) + 1;
|
||||
const char* script = "<script type=\"application/javascript\"
|
||||
src=\"webui.js\"></script> \n"; size_t new_len = strlen(user_html) +
|
||||
strlen(script) + 1;
|
||||
|
||||
// Allocate memory for the new string
|
||||
char* buffer = (char*) _webui_malloc(new_len);
|
||||
@ -6024,7 +6164,8 @@ static int _webui_http_log(const struct mg_connection* conn, const char* message
|
||||
// Construct the new HTML with script injected
|
||||
strncpy(buffer, user_html, offset); // Copy up to and including <head>
|
||||
strcpy(buffer + offset, script); // Copy the script
|
||||
strcpy(buffer + offset + strlen(script), user_html + offset); // Copy the rest of the user HTML
|
||||
strcpy(buffer + offset + strlen(script), user_html + offset); // Copy
|
||||
the rest of the user HTML
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@ -6103,7 +6244,8 @@ static int _webui_http_handler(struct mg_connection* conn, void* _win) {
|
||||
// Forbidden 403
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_http_handler() -> Embedded Index HTML Already Handled "
|
||||
printf("[Core]\t\t_webui_http_handler() -> Embedded Index HTML "
|
||||
"Already Handled "
|
||||
"(403)\n");
|
||||
#endif
|
||||
|
||||
@ -6136,7 +6278,8 @@ static int _webui_http_handler(struct mg_connection* conn, void* _win) {
|
||||
// Forbidden 403
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_http_handler() -> Index local file Already Handled "
|
||||
printf("[Core]\t\t_webui_http_handler() -> Index local file Already "
|
||||
"Handled "
|
||||
"(403)\n");
|
||||
#endif
|
||||
|
||||
@ -6240,8 +6383,8 @@ static int _webui_http_handler(struct mg_connection* conn, void* _win) {
|
||||
// // Forbidden 403
|
||||
|
||||
// #ifdef WEBUI_LOG
|
||||
// printf("[Core]\t\t_webui_http_handler() -> Local file .HTML Already Handled
|
||||
// (403)\n");
|
||||
// printf("[Core]\t\t_webui_http_handler() -> Local file .HTML
|
||||
// Already Handled (403)\n");
|
||||
// #endif
|
||||
|
||||
// _webui_http_send_error_page(
|
||||
@ -6261,7 +6404,8 @@ static int _webui_http_handler(struct mg_connection* conn, void* _win) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf(
|
||||
"[Core]\t\t_webui_http_handler() -> Trying to interpret local file (Runtime = "
|
||||
"[Core]\t\t_webui_http_handler() -> Trying to interpret local "
|
||||
"file (Runtime = "
|
||||
"%zu)\n",
|
||||
win->runtime
|
||||
);
|
||||
@ -6307,7 +6451,8 @@ static int _webui_ws_connect_handler(const struct mg_connection* conn, void* _wi
|
||||
|
||||
// Non-authorized connection
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_ws_connect_handler() -> Non-authorized connection.\n");
|
||||
printf("[Core]\t\t_webui_ws_connect_handler() -> Non-authorized "
|
||||
"connection.\n");
|
||||
#endif
|
||||
|
||||
// Block handshake
|
||||
@ -6453,8 +6598,7 @@ static WEBUI_THREAD_SERVER_START {
|
||||
WEBUI_SSL_EXPIRE_STR,
|
||||
#endif
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
NULL};
|
||||
struct mg_callbacks http_callbacks;
|
||||
struct mg_context* http_ctx;
|
||||
memset(&http_callbacks, 0, sizeof(http_callbacks));
|
||||
@ -6497,8 +6641,7 @@ static WEBUI_THREAD_SERVER_START {
|
||||
WEBUI_SSL_EXPIRE_STR,
|
||||
#endif
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
NULL};
|
||||
ws_mg_start_init_data.configuration_options = ws_server_options;
|
||||
struct mg_error_data ws_mg_start_error_data = {0};
|
||||
char ws_errtxtbuf[256] = {0};
|
||||
@ -6763,7 +6906,8 @@ static void _webui_receive(_webui_window_t* win, int event_type, void* data, siz
|
||||
// Received more data than expected
|
||||
#ifdef WEBUI_LOG
|
||||
printf(
|
||||
"[Core]\t\t_webui_receive()... > Multi packet received more data than expected (%zu + %zu "
|
||||
"[Core]\t\t_webui_receive()... > Multi packet received more data "
|
||||
"than expected (%zu + %zu "
|
||||
"> %zu).\n",
|
||||
multi_receive, len, multi_expect
|
||||
);
|
||||
@ -6790,7 +6934,8 @@ static void _webui_receive(_webui_window_t* win, int event_type, void* data, siz
|
||||
if (expect_len > 0 && expect_len <= WEBUI_MAX_BUF) {
|
||||
#ifdef WEBUI_LOG
|
||||
printf(
|
||||
"[Core]\t\t_webui_receive()... > Multi packet started, Expecting %zu bytes...\n",
|
||||
"[Core]\t\t_webui_receive()... > Multi packet started, "
|
||||
"Expecting %zu bytes...\n",
|
||||
expect_len
|
||||
);
|
||||
#endif
|
||||
@ -6874,24 +7019,36 @@ static WEBUI_THREAD_RECEIVE {
|
||||
uint16_t packet_id = _webui_get_id(packet);
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t[Thread %zu] _webui_receive_thread() -> Data received...\n", recvNum);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet Size : %zu bytes\n", recvNum,
|
||||
packet_len
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Data "
|
||||
"received...\n",
|
||||
recvNum
|
||||
);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet Size : "
|
||||
"%zu bytes\n",
|
||||
recvNum, packet_len
|
||||
);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet Header "
|
||||
": [ ",
|
||||
recvNum
|
||||
);
|
||||
printf("[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet Header : [ ", recvNum);
|
||||
_webui_print_hex(packet, WEBUI_PROTOCOL_SIZE);
|
||||
printf("]\n");
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet Token: 0x%08X (%" PRIu32 ")\n",
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet Token: "
|
||||
"0x%08X (%" PRIu32 ")\n",
|
||||
recvNum, packet_token, packet_token
|
||||
);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet ID: 0x%04X (%u)\n", recvNum,
|
||||
packet_id, packet_id
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet ID: "
|
||||
"0x%04X (%u)\n",
|
||||
recvNum, packet_id, packet_id
|
||||
);
|
||||
printf("[Core]\t\t[Thread %zu] _webui_receive_thread() -> Packet Data: [", recvNum);
|
||||
//_webui_print_ascii(&packet[WEBUI_PROTOCOL_DATA], (packet_len - WEBUI_PROTOCOL_SIZE));
|
||||
//_webui_print_ascii(&packet[WEBUI_PROTOCOL_DATA], (packet_len -
|
||||
// WEBUI_PROTOCOL_SIZE));
|
||||
printf("]\n");
|
||||
#endif
|
||||
|
||||
@ -6920,17 +7077,20 @@ static WEBUI_THREAD_RECEIVE {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> WEBUI_CMD_CLICK "
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> "
|
||||
"WEBUI_CMD_CLICK "
|
||||
"\n",
|
||||
recvNum
|
||||
);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Element size: "
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Element "
|
||||
"size: "
|
||||
"%zu bytes \n",
|
||||
recvNum, element_len
|
||||
);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Element : [%s] "
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Element "
|
||||
": [%s] "
|
||||
"\n",
|
||||
recvNum, element
|
||||
);
|
||||
@ -7120,12 +7280,14 @@ static WEBUI_THREAD_RECEIVE {
|
||||
recvNum
|
||||
);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Call ID: [%u] "
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Call ID: "
|
||||
"[%u] "
|
||||
"\n",
|
||||
recvNum, packet_id
|
||||
);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Element: [%s] "
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Element: "
|
||||
"[%s] "
|
||||
"\n",
|
||||
recvNum, element
|
||||
);
|
||||
@ -7272,7 +7434,8 @@ static WEBUI_THREAD_RECEIVE {
|
||||
#ifdef WEBUI_LOG
|
||||
else {
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Unknown command "
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Unknown "
|
||||
"command "
|
||||
"[0x%02x]\n",
|
||||
recvNum, (unsigned char)packet[WEBUI_PROTOCOL_CMD]
|
||||
);
|
||||
@ -7282,7 +7445,8 @@ static WEBUI_THREAD_RECEIVE {
|
||||
#ifdef WEBUI_LOG
|
||||
else {
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Window disconnected.\n",
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Window "
|
||||
"disconnected.\n",
|
||||
recvNum
|
||||
);
|
||||
}
|
||||
@ -7294,7 +7458,11 @@ static WEBUI_THREAD_RECEIVE {
|
||||
} else {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t[Thread %zu] _webui_receive_thread() -> Invalid Packet.\n", recvNum);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> Invalid "
|
||||
"Packet.\n",
|
||||
recvNum
|
||||
);
|
||||
#endif
|
||||
|
||||
// Forced close
|
||||
@ -7312,7 +7480,11 @@ static WEBUI_THREAD_RECEIVE {
|
||||
win->mg_connection = conn; // send
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t[Thread %zu] _webui_receive_thread() -> WebSocket connected\n", recvNum);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> WebSocket "
|
||||
"connected\n",
|
||||
recvNum
|
||||
);
|
||||
#endif
|
||||
|
||||
// New Event
|
||||
@ -7353,7 +7525,11 @@ static WEBUI_THREAD_RECEIVE {
|
||||
win->bridge_handled = false;
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t[Thread %zu] _webui_receive_thread() -> WebSocket Closed\n", recvNum);
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> WebSocket "
|
||||
"Closed\n",
|
||||
recvNum
|
||||
);
|
||||
#endif
|
||||
|
||||
// Events
|
||||
@ -7389,8 +7565,9 @@ static WEBUI_THREAD_RECEIVE {
|
||||
#ifdef WEBUI_LOG
|
||||
else {
|
||||
printf(
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> UNKNOWN EVENT TYPE (%zu)\n", recvNum,
|
||||
event_type
|
||||
"[Core]\t\t[Thread %zu] _webui_receive_thread() -> UNKNOWN EVENT "
|
||||
"TYPE (%zu)\n",
|
||||
recvNum, event_type
|
||||
);
|
||||
}
|
||||
#endif
|
||||
@ -7599,7 +7776,8 @@ static int _webui_system_win32_out(const char* cmd, char** output, bool show) {
|
||||
}
|
||||
|
||||
/*
|
||||
static BOOL CALLBACK _webui_enum_windows_proc_win32(HWND hwnd, LPARAM targetProcessId) {
|
||||
static BOOL CALLBACK _webui_enum_windows_proc_win32(HWND hwnd, LPARAM
|
||||
targetProcessId) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_enum_windows_proc_win32()...\n");
|
||||
@ -7611,8 +7789,8 @@ static BOOL CALLBACK _webui_enum_windows_proc_win32(HWND hwnd, LPARAM targetProc
|
||||
if (windowProcessId == targetProcessId) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[Core]\t\t_webui_enum_windows_proc_win32() -> Bring the process (%lu) to the front\n",
|
||||
windowProcessId); #endif
|
||||
printf("[Core]\t\t_webui_enum_windows_proc_win32() -> Bring the
|
||||
process (%lu) to the front\n", windowProcessId); #endif
|
||||
|
||||
SetFocus(hwnd);
|
||||
SetForegroundWindow(hwnd);
|
||||
@ -7647,9 +7825,10 @@ static int _webui_system_win32(_webui_window_t* win, char* cmd, bool show) {
|
||||
// webui.js will try to close the window.
|
||||
HANDLE JobObject = CreateJobObject(NULL, NULL);
|
||||
JOB_OBJECT_EXTENDED_LIMIT_INFORMATION ExtendedInfo = { 0 };
|
||||
ExtendedInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; SetInformationJobObject(JobObject, JobObjectExtendedLimitInformation,
|
||||
&ExtendedInfo, sizeof(ExtendedInfo));
|
||||
ExtendedInfo.BasicLimitInformation.LimitFlags =
|
||||
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; SetInformationJobObject(JobObject,
|
||||
JobObjectExtendedLimitInformation, &ExtendedInfo, sizeof(ExtendedInfo));
|
||||
*/
|
||||
|
||||
DWORD Return = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user