From cc41cee21814e7c96f62c1e042f47fd531f40437 Mon Sep 17 00:00:00 2001 From: Dustin Falgout Date: Thu, 1 Dec 2016 09:19:57 -0600 Subject: [PATCH] replace theme heartbeat as the implementation was flawed. instead check window object for existence of required theme functions and give user option to switch themes if check fails. --- src/greeter.c | 147 +++++++++++++++++------------ src/gresource/css/style.css | 5 + src/gresource/js/ThemeHeartbeat.js | 82 ---------------- src/gresource/js/ThemeUtils.js | 2 - 4 files changed, 92 insertions(+), 144 deletions(-) delete mode 100644 src/gresource/js/ThemeHeartbeat.js diff --git a/src/greeter.c b/src/greeter.c index 5f5b3e7..590dae6 100644 --- a/src/greeter.c +++ b/src/greeter.c @@ -69,17 +69,12 @@ static int static gint config_timeout; -static gboolean - debug_mode, - heartbeat, - heartbeat_exit; +static gboolean debug_mode; static void initialize_web_extensions_cb(WebKitWebContext *context, gpointer user_data) { - webkit_web_context_set_web_extensions_directory(context, WEBEXT_DIR); - } @@ -104,7 +99,6 @@ context_menu_cb(WebKitWebView *view, GdkEvent *event, WebKitHitTestResult *hit_test_result, gpointer user_data) { - /* Returning true without creating a custom context menu results in no context * menu being shown. Thus, we are returning the opposite of debug_mode to get * desired result (which is only show menu when debug_mode is enabled. @@ -113,50 +107,6 @@ context_menu_cb(WebKitWebView *view, } -static gboolean -check_theme_heartbeat(void) { - if (! heartbeat && ! heartbeat_exit) { - /* Theme heartbeat not received. We assume that an error has occurred - * which broke script execution. We will fallback to the simple theme - * so the user won't be stuck with a broken login screen. - */ - g_warning("[ERROR] :: A problem was detected with the current theme. Falling back to simple theme..."); - webkit_web_view_load_uri( - WEBKIT_WEB_VIEW(web_view), - g_strdup_printf("file://%ssimple/index.html", THEME_DIR) - ); - } - - heartbeat = FALSE; - - return heartbeat; -} - - -/** - * Callback for Theme Heartbeat. - */ -static void -theme_heartbeat_handler(void) { - if (! heartbeat) { - /* Setup g_timeout callback for theme heartbeat check */ - g_timeout_add_seconds(8, (GSourceFunc) check_theme_heartbeat, NULL); - heartbeat = TRUE; - heartbeat_exit = FALSE; - } -} - - -/** - * Before starting the user's session, the web process will send a signal to exit the hearbeat - * in order to prevent a race condition while the greeter is shutting down. - */ -static void -theme_heartbeat_exit_handler(void) { - heartbeat_exit = TRUE; -} - - /** * Makes the greeter behave a bit more like a screensaver if it was launched as * a lock-screen by blanking the screen. @@ -210,17 +160,11 @@ message_received_cb(WebKitUserContentManager *manager, if (strcmp(message_str, "LockHint") == 0) { lock_hint_enabled_handler(); - } else if (strcmp(message_str, "Heartbeat") == 0) { - theme_heartbeat_handler(); - - } else if (strcmp(message_str, "Heartbeat::Exit") == 0) { - theme_heartbeat_exit_handler(); } else { printf("UI PROCESS - message_received_cb(): no match!"); } g_free(message_str); - } @@ -275,6 +219,89 @@ javascript_bundle_injection_setup() { } +static void +theme_function_exists_cb(GObject *object, + GAsyncResult *result, + gpointer user_data) { + + WebKitJavascriptResult *js_result; + GError *error = NULL; + JSValueRef value; + JSGlobalContextRef context; + gboolean result_as_bool; + + js_result = webkit_web_view_run_javascript_finish(WEBKIT_WEB_VIEW(object), result, &error); + + if (NULL != error) { + g_warning ("Error running javascript: %s", error->message); + g_error_free(error); + return; + + } else { + context = webkit_javascript_result_get_global_context(js_result); + value = webkit_javascript_result_get_value(js_result); + + result_as_bool = JSValueToBoolean(context, value); + } + + if (FALSE == result_as_bool) { + GtkWidget *dialog, *label, *content_area, *button, *button_box; + + dialog = gtk_dialog_new_with_buttons( + _("Greeter Theme Error Detected"), + GTK_WINDOW(window), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + _("_Load Default Theme"), + GTK_RESPONSE_ACCEPT, + _("_Load Fallback Theme"), + GTK_RESPONSE_OK, + _("_Cancel"), + GTK_RESPONSE_REJECT, + NULL + ); + content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + button = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_REJECT); + button_box = gtk_widget_get_parent(button); + label = gtk_label_new(_("An error was detected in the current theme that could interfere with the system login process.")); + + gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_EXPAND); + gtk_container_add(GTK_CONTAINER(content_area), label); + gtk_widget_show_all(content_area); + + gint response = gtk_dialog_run(GTK_DIALOG(dialog)); + gchar *log_msg = "[ERROR] :: A problem was detected with the current theme. Falling back to simple theme..."; + + if (GTK_RESPONSE_ACCEPT == response) { + g_warning(log_msg); + webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), g_strdup_printf("file://%s/antergos/index.html", THEME_DIR)); + + } else if (GTK_RESPONSE_OK == response) { + g_warning(log_msg); + webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), g_strdup_printf("file://%s/simple/index.html", THEME_DIR)); + } + + gtk_widget_destroy(dialog); + } + + webkit_javascript_result_unref(js_result); +} + + +gboolean +maybe_show_theme_fallback_dialog(void) { + /* Check for existence of a function that themes must add to window object */ + webkit_web_view_run_javascript( + WEBKIT_WEB_VIEW(web_view), + "(() => 'authentication_complete' in window)()", + NULL, + (GAsyncReadyCallback) theme_function_exists_cb, + NULL + ); + + return FALSE; +} + + int main(int argc, char **argv) { GdkScreen *screen; @@ -355,9 +382,6 @@ main(int argc, char **argv) { gdk_window_set_cursor(root_window, gdk_cursor_new_for_display(default_display, GDK_LEFT_PTR)); - /* Set the GTK theme to Adwaita */ - g_object_set(gtk_settings_get_default(), "gtk-theme-name", "Adwaita", NULL); - /* Setup the main window */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); screen = gtk_window_get_screen(GTK_WINDOW(window)); @@ -426,6 +450,9 @@ main(int argc, char **argv) { /* Maybe disable the context (right-click) menu. */ g_signal_connect(WEBKIT_WEB_VIEW(web_view), "context-menu", G_CALLBACK(context_menu_cb), NULL); + /* Register callback to check if theme loaded successfully */ + g_timeout_add_seconds(5, (GSourceFunc) maybe_show_theme_fallback_dialog, NULL); + /* There's no turning back now, let's go! */ gtk_container_add(GTK_CONTAINER(window), web_view); webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), diff --git a/src/gresource/css/style.css b/src/gresource/css/style.css index 8cd1492..d279f09 100644 --- a/src/gresource/css/style.css +++ b/src/gresource/css/style.css @@ -2,3 +2,8 @@ window, GtkWindow { background: #000000; } + +dialog .dialog-vbox > label, +GtkDialog .dialog-vbox > GtkLabel { + margin: 20px 15px; +} diff --git a/src/gresource/js/ThemeHeartbeat.js b/src/gresource/js/ThemeHeartbeat.js deleted file mode 100644 index 1939fe4..0000000 --- a/src/gresource/js/ThemeHeartbeat.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ThemeHeartbeat.js - * - * Copyright © 2016 Antergos Developers - * - * This file is part of lightdm-webkit2-greeter. - * - * lightdm-webkit2-greeter is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * lightdm-webkit2-greeter is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * The following additional terms are in effect as per Section 7 of the license: - * - * The preservation of all legal notices and author attributions in - * the material or in the Appropriate Legal Notices displayed - * by works containing it is required. - * - * You should have received a copy of the GNU General Public License - * along with lightdm-webkit2-greeter; If not, see . - */ - - -/** - * Singleton class for the greeter theme heartbeat. - * - * Once instantiated, the instance will begin sending a heartbeat message to the greeter - * every 5 seconds. Upon receiving the first heartbeat message, the greeter will schedule checks - * to ensure that subsequent heartbeat messages are received. - * - * If a heartbeat message is not received by the time any of the greeter's - * subsequent checks run, it will assume that there has been an error in the theme's script - * execution and fall back to the simple theme. - */ -class ThemeHeartbeat { - - constructor() { - if ( '__heartbeat' in window ) { - return __heartbeat; - } - - window.__heartbeat = theme_utils.bind_this(this); - this.heartbeat = ''; - this.heartbeats = 0; - - this.initialize_theme_heartbeat(); - - return window.__heartbeat; - } - - initialize_theme_heartbeat() { - if ( '' !== this.heartbeat ) { - console.log( 'Heartbeat has already been initialized!' ); - return; - } - - console.log('Initializing theme heartbeat.'); - - this.send_heartbeat(); - this.heartbeat = setInterval(this.send_heartbeat, 5000); - } - - send_heartbeat() { - ++this.heartbeats; - - if ( true === lightdm.session_starting ) { - clearInterval( this.heartbeat ); - return; - } - - if ( this.heartbeats < 2 ) { - console.log('Sending heartbeat...'); - } - - window.webkit.messageHandlers.GreeterBridge.postMessage('Heartbeat'); - } -} diff --git a/src/gresource/js/ThemeUtils.js b/src/gresource/js/ThemeUtils.js index 7c7c8e0..20cef60 100644 --- a/src/gresource/js/ThemeUtils.js +++ b/src/gresource/js/ThemeUtils.js @@ -227,8 +227,6 @@ const __theme_utils = new Promise( (resolve, reject) => { __theme_utils.then( result => { window.theme_utils = result; - new ThemeHeartbeat(); - /** * @deprecated * @type {LightDM.ThemeUtils}