Skip to content

Instantly share code, notes, and snippets.

@aperezdc
Last active March 6, 2023 11:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aperezdc/621c1ec6bb78923e27fc035fa0689522 to your computer and use it in GitHub Desktop.
Save aperezdc/621c1ec6bb78923e27fc035fa0689522 to your computer and use it in GitHub Desktop.
Minimal WPE launcher, with user message handler to poweroff/reboot a device
/*
* SPDX-License-Identifier: MIT
*
* cc -o minicog minicog.c $(pkg-config wpe-webkit-1.1 cogcore --cflags --libs)
*/
#include <cog/cog.h>
#include <sys/reboot.h>
static const char *s_starturl = NULL;
static void
handle_power_control_message(WebKitUserContentManager *content_manager,
WebKitJavascriptResult *js_result, void *userdata)
{
JSCValue *value = webkit_javascript_result_get_js_value(js_result);
if (!jsc_value_is_string(value)) {
g_warning("Invalid powerControl message: argument is not a string");
return;
}
g_autofree char *value_as_string = jsc_value_to_string(value);
int action;
if (strcmp(value_as_string, "poweroff") == 0) {
action = RB_POWER_OFF;
} else if (strcmp(value_as_string, "reboot") == 0) {
action = RB_AUTOBOOT;
} else {
g_warning("Invalid powerControl message: '%s'", value_as_string);
return;
}
g_message("Device will %s now!", value_as_string);
/*
* This fails unless the process is run as "root" (not recommended!)
* or has been granted the CAP_SYS_BOOT capability. In reality, this
* should probably call the org.freedesktop.systemd1.Reboot() method
* and friends using D-Bus instead.
*/
sync();
reboot(action);
}
static WebKitUserContentManager*
create_content_manager(void)
{
g_autoptr(WebKitUserContentManager) content_manager = webkit_user_content_manager_new();
webkit_user_content_manager_register_script_message_handler(content_manager, "powerControl");
g_signal_connect(content_manager, "script-message-received::powerControl",
G_CALLBACK(handle_power_control_message), NULL);
return g_steal_pointer(&content_manager);
}
static WebKitWebView*
on_create_view(CogShell *shell, CogPlatform *platform)
{
g_autoptr(GError) error = NULL;
WebKitWebViewBackend *view_backend = cog_platform_get_view_backend(platform, NULL, &error);
if (!view_backend)
g_error("Cannot obtain view backend: %s", error->message);
g_autoptr(WebKitUserContentManager) content_manager = create_content_manager();
WebKitSettings *settings = cog_shell_get_web_settings(shell);
webkit_settings_set_enable_write_console_messages_to_stdout(settings, TRUE);
g_autoptr(WebKitWebView) web_view =
g_object_new(WEBKIT_TYPE_WEB_VIEW,
"user-content-manager", content_manager,
"settings", settings,
"web-context", cog_shell_get_web_context(shell),
"backend", view_backend,
NULL);
cog_platform_init_web_view(platform, web_view);
webkit_web_view_load_uri(web_view, s_starturl);
return g_steal_pointer(&web_view);
}
int
main(int argc, char *argv[])
{
g_set_application_name("minicog");
if (argc != 2 && argc != 3) {
g_printerr("Usage: %s [URL [platform]]\n", argv[0]);
return EXIT_FAILURE;
}
g_autoptr(GError) error = NULL;
if (!(s_starturl = cog_uri_guess_from_user_input(argv[1], TRUE, &error)))
g_error("Invalid URL '%s': %s", argv[1], error->message);
cog_modules_add_directory(COG_MODULEDIR);
g_autoptr(GApplication) app = g_application_new(NULL, G_APPLICATION_DEFAULT_FLAGS);
g_autoptr(CogShell) shell = cog_shell_new("minicog", FALSE);
g_autoptr(CogPlatform) platform =
cog_platform_new((argc == 3) ? argv[2] : g_getenv("COG_PLATFORM"), &error);
if (!platform)
g_error("Cannot create platform: %s", error->message);
if (!cog_platform_setup(platform, shell, "", &error))
g_error("Cannot setup platform: %s\n", error->message);
g_signal_connect(shell, "create-view", G_CALLBACK(on_create_view), platform);
g_signal_connect_swapped(app, "shutdown", G_CALLBACK(cog_shell_shutdown), shell);
g_signal_connect_swapped(app, "startup", G_CALLBACK(cog_shell_startup), shell);
g_signal_connect(app, "activate", G_CALLBACK(g_application_hold), NULL);
return g_application_run(app, 1, argv);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Device Power Control</title>
</head>
<body>
<button id="reboot">Reboot</button>
<button id="poweroff">Power Off</button>
<script type="text/javascript">
function addHandler(name) {
document.getElementById(name).addEventListener("click", (event) => {
window.webkit.messageHandlers.powerControl.postMessage(name);
return false;
});
}
addHandler("reboot");
addHandler("poweroff");
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment