Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion nyxt.asd
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@
(:file "prompt-buffer")
(:file "command-commands")
(:file "recent-buffers")
(:file "external-editor")))
(:file "external-editor")
(:file "mode/incognito")))
(:module "Core modes"
:pathname "mode"
:depends-on ("Core")
Expand Down
6 changes: 5 additions & 1 deletion source/buffer.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,11 @@ down."))
:initform :renderer
:type symbol
:documentation "Select a download engine to use, such as `:lisp' or
`:renderer'."))
`:renderer'.")
(web-context-name
"default"
:type string
:documentation "Name of the renderer web context for this buffer. Use \"incognito\" to use a non-persistent context."))
(:export-class-name-p t)
(:export-accessor-names-p t)
(:export-predicate-name-p t)
Expand Down
17 changes: 9 additions & 8 deletions source/mode/history.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,16 @@

(defmethod add-url-to-history (url (mode history-mode) &key (title ""))
"Push URL to `history-vector'."
(unless (blocked-p url mode)
(unless (or (blocked-p url mode)
(nyxt:find-submode 'nyxt/mode/incognito:incognito-mode (buffer mode)))
(with-slots (history-vector history-file) *browser*
(vector-push-extend (make-instance 'history-entry
:url (quri:uri url)
:title title)
history-vector)
(files:with-file-content (history history-file)
(setf history history-vector))
url)))
(vector-push-extend (make-instance 'history-entry
:url (quri:uri url)
:title title)
history-vector)
(files:with-file-content (history history-file)
(setf history history-vector))
url)))

(defmethod nyxt:on-signal-load-finished ((mode history-mode) url title)
(add-url-to-history url mode :title title)
Expand Down
34 changes: 34 additions & 0 deletions source/mode/incognito.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
;;;; SPDX-FileCopyrightText: Atlas Engineer LLC
;;;; SPDX-License-Identifier: BSD-3-Clause

(nyxt:define-package :nyxt/mode/incognito
(:documentation "Incognito mode: isolate session data for this buffer."))

(in-package :nyxt/mode/incognito)

(define-mode incognito-mode ()
"Mode to browse without persisting data. Uses a separate web context."
((visible-in-status-p t)
(glyph "🕶")
(keyscheme-map (define-keyscheme-map "incognito-mode" ()
keyscheme:default
(list)))
(rememberable-p nil))
(:documentation "When enabled, the buffer uses a non-persistent renderer context
with no persistent cookies and no global history writes."))

(defmethod enable :after ((mode incognito-mode) &key &allow-other-keys)
(let* ((buffer (buffer mode)))
;; Switch buffer to use the incognito web context.
(setf (slot-value buffer 'nyxt::web-context-name) "incognito")
;; Also prevent history entries on this buffer by removing history-mode if present.
(when (nyxt:find-submode 'nyxt/mode/history:history-mode buffer)
(nyxt:disable-modes* 'nyxt/mode/history:history-mode buffer))))

(define-command-global open-incognito (&key (url (nyxt:default-new-buffer-url nyxt:*browser*)))
"Open a new incognito buffer."
(let ((buffer (nyxt:make-buffer :buffer-class 'nyxt:web-buffer
:url url
:modes '(nyxt/mode/incognito:incognito-mode))))
(nyxt:set-current-buffer buffer)
buffer))
58 changes: 56 additions & 2 deletions source/renderer/gtk.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@
(defmethod get-web-context ((browser gtk-browser) name)
(alexandria:ensure-gethash name
(web-contexts browser)
(make-web-context)))
(if (string= name "incognito")
(make-web-context-incognito)
(make-web-context))))

(defmethod browser-schemes append ((browser gtk-browser))
'("webkit" "webkit-pdfjs-viewer"))
Expand Down Expand Up @@ -287,6 +289,54 @@ the renderer thread, use `defmethod' instead."
(setf (ffi-buffer-cookie-policy cookie-manager) (default-cookie-policy *browser*))
context))

(defun make-web-context-incognito ()
"Create a WebKit web context without persistent storage for cookies.
Other settings mirror `make-web-context'."
(let* ((context (make-instance 'webkit:webkit-web-context
:website-data-manager
(make-instance 'webkit-website-data-manager)))
(cookie-manager (webkit:webkit-web-context-get-cookie-manager context))
(gtk-extensions-path (files:expand (make-instance 'gtk-extensions-directory))))
(webkit:webkit-web-context-set-spell-checking-enabled context t)
;; Need to set the initial language list.
(let ((pointer (cffi:foreign-alloc :string
:initial-contents (list (or (uiop:getenv "LANG")
(uiop:getenv "LANGUAGE")
(uiop:getenv "LC_CTYPE")
"en_US"))
:null-terminated-p t)))
(webkit:webkit-web-context-set-spell-checking-languages context pointer)
(cffi:foreign-free pointer))
(when (and (not (nfiles:nil-pathname-p gtk-extensions-path))
(or (uiop:directory-exists-p gtk-extensions-path)
(handler-case
(nth-value 1 (ensure-directories-exist gtk-extensions-path))
(file-error ()))))
(log:info "GTK extensions directory: ~s" gtk-extensions-path)
(gobject:g-signal-connect
context "initialize-web-extensions"
(lambda (context)
(with-protect ("Error in \"initialize-web-extensions\" signal thread: ~a" :condition)
(webkit:webkit-web-context-set-web-extensions-directory
context
(uiop:native-namestring gtk-extensions-path))))))
(gobject:g-signal-connect
context "download-started"
(lambda (context download)
(declare (ignore context))
(with-protect ("Error in \"download-started\" signal thread: ~a" :condition)
(wrap-download download))))
(maphash (lambda (scheme-name callbacks)
(ffi-register-custom-scheme (make-instance 'scheme
:name scheme-name
:web-context context
:callback (first callbacks)
:error-callback (second callbacks))))
nyxt::*schemes*)
;; IMPORTANT: Do NOT set persistent cookie storage here for incognito.
(setf (ffi-buffer-cookie-policy cookie-manager) (default-cookie-policy *browser*))
context))

(define-class gtk-request-data ()
((gtk-request
:type (maybe webkit:webkit-uri-request))
Expand Down Expand Up @@ -1173,7 +1223,11 @@ with this scheme.")
;; A single web view is shared by all prompt buffers of a window.
(prompt-buffer-view (window buffer))
(make-instance 'webkit:webkit-web-view
:web-context (get-web-context *browser* "default"))))
:web-context (get-web-context *browser*
(if (and (typep buffer 'nyxt:context-buffer)
(slot-boundp buffer 'nyxt::web-context-name))
(slot-value buffer 'nyxt::web-context-name)
"default")))))
(when (document-buffer-p buffer)
(setf (ffi-buffer-smooth-scrolling-enabled-p buffer) (smooth-scrolling buffer)))
;; TODO: Maybe define an FFI method?
Expand Down