gpointer data);
 static void dbus_call(Client *c, const char *method, GVariant *param,
         GAsyncReadyCallback callback);
+static GVariant *dbus_call_sync(Client *c, const char *method, GVariant
+        *param);
 static void on_web_extension_page_created(GDBusConnection *connection,
         const char *sender_name, const char *object_path,
         const char *interface_name, const char *signal_name,
        }
 }
 
+GVariant *ext_proxy_eval_script_sync(Client *c, char *js)
+{
+    return dbus_call_sync(c, "EvalJs", g_variant_new("(s)", js));
+}
+
 /**
  * Request the web extension to focus first editable element.
  * Returns whether an focusable element was found or not.
     g_dbus_proxy_call(c->dbusproxy, method, param, G_DBUS_CALL_FLAGS_NONE, -1, NULL, callback, c);
 }
 
+/**
+ * Call a dbus method syncron.
+ */
+static GVariant *dbus_call_sync(Client *c, const char *method, GVariant *param)
+{
+       GVariant *result = NULL;
+    GError *error = NULL;
+
+    if (!c->dbusproxy) {
+        return NULL;
+    }
+
+    result = g_dbus_proxy_call_sync(c->dbusproxy, method, param,
+        G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+
+    if (error) {
+        g_warning("Failed dbus method %s: %s", method, error->message);
+        g_error_free(error);
+    }
+
+       return result;
+}
+
 /**
  * Called when the web context created the page.
  *
 
 
 extern struct Vimb vb;
 
-static void call_hints_function(Client *c, const char *func, const char* args);
+static gboolean call_hints_function(Client *c, const char *func, const char* args);
 static void fire_timeout(Client *c, gboolean on);
 static gboolean fire_cb(gpointer data);
 
         hints_fire(c);
 
         return RESULT_COMPLETE;
-    } else if (key == CTRL('H')) {
+    } else if (key == CTRL('H')) { /* backspace */
         fire_timeout(c, false);
-        call_hints_function(c, "update", "null");
-        return RESULT_MORE; // continue handling the backspace
+        if (call_hints_function(c, "update", "null")) {
+            return RESULT_COMPLETE;
+        }
     } else if (key == KEY_TAB) {
         fire_timeout(c, false);
         hints_focus_next(c, false);
     } else {
         fire_timeout(c, true);
         /* try to handle the key by the javascript */
-        call_hints_function(c, "update", (char[]){'"', key, '"', '\0'});
-        return RESULT_ERROR;
+        if (call_hints_function(c, "update", (char[]){'"', key, '"', '\0'})) {
+            return RESULT_COMPLETE;
+        }
     }
 
     fire_timeout(c, false);
     return res;
 }
 
-static void hints_function_callback(GDBusProxy *proxy, GAsyncResult *result, Client *c)
+static gboolean call_hints_function(Client *c, const char *func, const char* args)
 {
+    GVariant *return_value;
+    char *jscode, *value = NULL;
     gboolean success = FALSE;
-    char *value = NULL;
 
-    GVariant *return_value = g_dbus_proxy_call_finish(proxy, result, NULL);
+    jscode = g_strdup_printf("hints.%s(%s);", func, args);
+    return_value = ext_proxy_eval_script_sync(c, jscode);
+    g_free(jscode);
+
     if (!return_value) {
-        return;
+        return FALSE;
     }
 
     g_variant_get(return_value, "(bs)", &success, &value);
-    if (!success) {
-        return;
-    }
-
-    if (!strncmp(value, "ERROR:", 6)) {
-        return;
+    if (!success || !strncmp(value, "ERROR:", 6)) {
+        return FALSE;
     }
 
     /* following return values mark fired hints */
 #endif
         }
     }
-}
 
-static void call_hints_function(Client *c, const char *func, const char* args)
-{
-    char *jscode;
-
-    jscode = g_strdup_printf("hints.%s(%s);", func, args);
-    ext_proxy_eval_script(c, jscode, (GAsyncReadyCallback)hints_function_callback);
-    g_free(jscode);
+    return TRUE;
 }
 
 static void fire_timeout(Client *c, gboolean on)