Complete Computing Environment: Web Browsing

Table of Contents

Web Browsing using EWW and Firefox

Web browsing is still hard; I want to use the Emacs-native EWW, but without native Javascript or anything that makes the modern "Web Apps" I use at work, well, work, I need a GUI browser. Right now my GUI browser of choice is Firefox, which provides enough keyboard-driven facilities as well as performance that is bearable.

(provide 'cce-browsers)

We can browse to anything that looks like a URL with SPC u.

(evil-leader/set-key (kbd "u") 'browse-url-at-point)

I use EWW as my default browser in Emacs; certain things, I need to jump out of EWW and in to a real browser with javascript; which I can do if I just hit & – it'll drop me in to a firefox session without a hassle.

There are certain sites that, despite my best abilities, I cannot make work in EWW. For these, I launch Firefox directly, instead of hitting a silly man in the middle. Eventually I'll probably try Qutebrowser again, but what I really want in life is Qutebrowser, but with Mozilla's tech driving it.

(setq browse-url-generic-program (executable-find "firefox"))

(setq browse-url-browser-function
   '(("https?://[a-z0-9.]*" . browse-url-generic)
     ("https?://*" . browse-url-generic)
     (".*" . eww-browse-url)))


I use this advice to rename all of the EWW buffers based on their <title> elements.

(defadvice eww-tag-title (after rrix/eww-rename-buffer-ad (cont))
    "Update EWW buffer title with new page load."
    (let ((eww-current-title (plist-get eww-data :title)))
      (rename-buffer (format "*eww : %s *" (cce/str-chomp eww-current-title)) t)))
(ad-activate 'eww-tag-title)

Always open links in existing window, if possible.

(setq browse-url-new-window-flag t)

Part of my Expansion technique is to just open a shitload of browser buffers throughout the day and pick through them in my IDLE times. EWW has basically no session support like emacs-w3m does, which is actually Okay given that that didn't serialize out to any format which I can sync between my workstations easily. Instead, I've crafted this function which uses my W buffer capture template to dump every EWW buffer to my refile.

(install-pkgs '(el-pocket))
(load-library "el-pocket")
(defun rrix/capture-all-eww-buffers ()
  (map 'list (lambda (b)
               (with-current-buffer b
                 (when (eq major-mode 'eww-mode)
                   (let ((url(plist-get eww-data :url))
                         (title (plist-get eww-data :title)))
                     (if (y-or-n-p (format "Capture %s (%s)? " title url))
                           (el-pocket-add url))

Having a global history is an incredibly useful thing to have but EWW doesn't give me one of these out of the box; I advise this in after eww-render like so:

(defvar rrix/eww-global-history '())
(defadvice eww-render (after rrix/eww-global-history-ad ())
  "Add EWW history to a global history variable"
  (push (list :url (plist-get eww-data :url)
              :title (plist-get eww-data :title)
              :point (point)
              :date (format-time-string "%FT%T%z"))
(ad-activate 'eww-render)
(add-to-list 'savehist-additional-variables 'rrix/eww-global-history)

I'll need to find some way to load that in to eww-list-histories, though… This is close, but it doesn't work since I'm not loading the full DOM, source and text in to the variable.

(defun rrix/list-eww-histories ()
  (with-current-buffer (get-buffer-create "*eww-global-history*")
    (setq-local eww-history rrix/eww-global-history)

eww-lnum is a package that lets you follow any URL in an eww buffer with a keybinding, similar to Avy

(install-pkgs '(eww-lnum))
(eval-after-load 'eww-mode
  (lambda ()
    (define-key eww-mode-map "f" 'eww-lnum-follow)))


- name: firefox installed
    state: installed
    name: firefox
  when: ansible_pkg_mgr == "apt"

- name: firefox installed
    state: installed
    name: firefox
  when: ansible_pkg_mgr == "dnf"

KDE Plasma has a new feature for integrating browsers in to the OS by combining a native d-bus service and a browser WebExtension. The Emacs d-bus library lets us use it to do an ivy integration to swap Firefox tabs.

(require 'dbus)

(defun cce/browser-activate-tabs-cb (choice)
  (funcall dbus "Activate" :int32 (truncate (string-to-number (gethash choice ivy-hash)))))

(defun browser-activate-tab ()
  "Activate a browser tab using Ivy. Requires plasma-browser integration"
  (let ((ivy-hash (make-hash-table :test 'equal))
        (dbus (apply-partially 'dbus-call-method :session
                               "org.kde.plasma.browser_integration" "/TabsRunner"
    (let ((cb #'cce/browser-activate-tabs-cb)
          (res (funcall dbus "GetTabs")))
       (lambda (obj)
         (let ((id (number-to-string (car (car (alist-get "id" (car obj) nil nil #'equal)))))
               (title (car (car (alist-get "title" (car obj) nil nil #'equal)))))
           (puthash title id ivy-hash)))
      (ivy-read "Activate tab: " ivy-hash :action cb))))

(define-key exwm-mode-map (kbd "<XF86Tools>") #'browser-activate-tab)
(define-key exwm-mode-map (kbd "<f8>") #'browser-activate-tab)

Customizing Firefox

Everyone is up in arms about Firefox Quantum removing core features, but it seems like we're doing alright. Firefox's work on building out WebExtension-based APIs gives us a good shot to customize it even in this new ecosystem. These are all from Timvde/UserChrome-Tweaks and modified to taste.

Hide the tab toolbar since I'm using the venerable Tree Style Tabs.

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at */

#TabsToolbar {
    visibility: collapse !important;

I like having the tabs sidebar auto-hide, this does that, and makes the handle on the left-side match the background color of the URL bar.

:root {
    --sidebar-hover-width: 10px;
    --sidebar-visible-width: 300px;

#sidebar-box {
    position: relative !important;
    overflow-x: hidden !important;
    margin-right: calc(var(--sidebar-hover-width) * -1) !important;
    left: var(--sidebar-hover-width) !important;
    min-width: var(--sidebar-hover-width) !important;
    max-width: var(--sidebar-hover-width) !important;

    transition-property: max-width margin-right left;
    transition-duration: 0.1s;
    background-color: var(--url-and-searchbar-background-color, hsla(0,0%,10%,.8)) !important;

#sidebar-box:hover {
    margin-right: calc(var(--sidebar-visible-width) * -1) !important;
    left: var(--sidebar-visible-width) !important;
    min-width: var(--sidebar-visible-width) !important;
    max-width: var(--sidebar-visible-width) !important;

    background-color: var(--url-and-searchbar-background-color, hsla(0,0%,10%,.8)) !important;

#sidebar {
    opacity: 0 !important;

#sidebar:hover {
    opacity: 1 !important;

/* #sidebar-header is hidden by default, change "none" to "inherit" to restore it. */
#sidebar-header {
    display: none !important;

/* #sidebar-splitter styles the divider between the sidebar and the rest of the browser. */
#sidebar-splitter {
    background-color: var(--url-and-searchbar-background-color, hsla(0,0%,10%,.8)) !important;

This pushes the find-text bar to the top and to the right rather than the bottom.

.browserContainer > findbar {
    -moz-box-ordinal-group: 0;
    position: fixed !important;
    right: 1em;
    border: 1px solid threedshadow !important;

    /* Hide the "border" at the top by removing the box-shadow and background-image */
    border-top: none !important;
    box-shadow: none !important;
    background-image: none !important;

    transition: 400ms !important;
    z-index: 0 !important;

findbar[hidden]{ margin-top: -2em !important; }

.findbar-closebutton {
    margin-inline-start: 0.5em !important;
    vertical-align: middle !important;
    margin-bottom: 0.25em !important;
    height: inherit !important;

Make the default browser background dark instead of light. Why this isn't in the dark theme by default is beyond me.

.browserContainer {
    background-color: var(--url-and-searchbar-background-color, hsla(0,0%,100%,.8)) !important;
- name: find userChrome.css directory
  shell: ls -d ~/.mozilla/firefox/*default/
  register: user_chrome_path

- name: userChrome.css installed
    src: out/userChrome.css
    dest: "{{user_chrome_path}}/chrome/userChrome.css

Author: Ryan Rix

Created: 2019-03-14 Thu 23:10

Validate XHTML 1.0