webkit_user_script_unref(script);
     }
 
-    /* Inject the global utility script. */
-    script = webkit_user_script_new(VIMB_UTIL,
-            WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
-            WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, NULL, NULL);
-    webkit_user_content_manager_add_script(ucm, script);
-    webkit_user_script_unref(script);
-
     /* Setup script message handlers. */
     webkit_user_content_manager_register_script_message_handler(ucm, "focus");
     g_signal_connect(ucm, "script-message-received::focus", G_CALLBACK(on_script_message_focus), c);
 
 static void dbus_handle_method_call(GDBusConnection *conn, const char *sender,
         const char *object_path, const char *interface_name, const char *method,
         GVariant *parameters, GDBusMethodInvocation *invocation, gpointer data);
+static void on_editable_change_focus(WebKitDOMEventTarget *target,
+        WebKitDOMEvent *event, WebKitWebExtension *extension);
 static void on_page_created(WebKitWebExtension *ext, WebKitWebPage *webpage, gpointer data);
 static void on_web_page_document_loaded(WebKitWebPage *webpage, gpointer extension);
 static gboolean on_web_page_send_request(WebKitWebPage *webpage, WebKitURIRequest *request,
 static void add_onload_event_observers(WebKitDOMDocument *doc,
         WebKitWebExtension *extension)
 {
-#if 0 /* might soon be use for some events */
     WebKitDOMEventTarget *target;
 
     /* Add the document to the table of known documents or if already exists
      * function is called with content document of an iframe. Else the event
      * observing does not work. */
     target = WEBKIT_DOM_EVENT_TARGET(webkit_dom_document_get_default_view(doc));
-#endif
+
+    webkit_dom_event_target_add_event_listener(target, "focus",
+            G_CALLBACK(on_editable_change_focus), TRUE, extension);
+    webkit_dom_event_target_add_event_listener(target, "blur",
+            G_CALLBACK(on_editable_change_focus), TRUE, extension);
+    /* Check for focused editable elements also if they where focused before
+     * the event observer where set up. */
+    /* TODO this is not needed for strict-focus=on */
+    on_editable_change_focus(target, NULL, extension);
 }
 
 /**
     }
 }
 
+/**
+ * Callback called if a editable element changes it focus state.
+ * Event target may be a WebKitDOMDocument (in case of iframe) or a
+ * WebKitDOMDOMWindow.
+ */
+static void on_editable_change_focus(WebKitDOMEventTarget *target,
+        WebKitDOMEvent *event, WebKitWebExtension *extension)
+{
+    gboolean input_focus;
+    WebKitDOMDocument *doc;
+    WebKitDOMDOMWindow *dom_window;
+    WebKitDOMElement *active;
+
+    if (WEBKIT_DOM_IS_DOM_WINDOW(target)) {
+        g_object_get(target, "document", &doc, NULL);
+    } else {
+        /* target is a doc document */
+        doc = WEBKIT_DOM_DOCUMENT(target);
+    }
+
+    dom_window = webkit_dom_document_get_default_view(doc);
+    if (!dom_window) {
+        return;
+    }
+
+    active = webkit_dom_document_get_active_element(doc);
+    /* Don't do anything if there is no active element or the active element
+     * is the same as before. */
+    if (!active || active == ext.active) {
+        return;
+    }
+    if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT(active)) {
+        WebKitDOMHTMLIFrameElement *iframe;
+        WebKitDOMDocument *subdoc;
+
+        iframe = WEBKIT_DOM_HTML_IFRAME_ELEMENT(active);
+        subdoc = webkit_dom_html_iframe_element_get_content_document(iframe);
+        add_onload_event_observers(subdoc, extension);
+        return;
+    }
+
+    ext.active = active;
+
+    /* Check if the active element is an editable element. */
+    input_focus = ext_dom_is_editable(active);
+    if (input_focus != ext.input_focus) {
+        ext.input_focus = input_focus;
+
+        webkit_dom_document_get_default_view(doc);
+        if (!webkit_dom_dom_window_webkit_message_handlers_post_message(dom_window, "focus", input_focus ? "1" : "0")) {
+            g_warning("Error sending focus message");
+            return;
+        }
+    }
+    g_object_unref(dom_window);
+}
+
 /**
  * Callback for web extensions page-created signal.
  */