overall, this design should give no preference to any form of software
or protocol.
all dispatch should be handled within the WM, via a custom wayland
protocol.
some mechanism for informing the WM of protocol handlers, probably a
registry on-disk.
protocol handlers are servers that listen for an event on the wayland
socket, that looks like
request:
URI: string
isWrite: bool
writer: fileDesc?
metadata: dict<string, string>
isWrite indicates a write operation, may be folded into writer as
optional. write operation translates 1:1 for file:// or sftp://, should
indicate POST under http://. metadata is protocol-specific, possibly
include an xmlns-alike. HTTP headers should be under one top-level key,
not inlined.
a request should return an error or a response.
a request error is a fatal error, not a protocol-level error.
a 404 is not a request error, a DNS lookup failure is.
a response is a sum type with variants:
tab:
/* necessary wayland metadata */
data:
mimeType: string
filename: string?
data: fileDesc
writable: bool
metadata: dict<string, string>
redirect:
URI: string
tab allows a protocol handler to directly display data to the user.
for example, an ssh handler may route URIs like ssh://host to a host,
but route URIs like ssh:///config to a settings menu that is rendered
internally.
data is delegated to a program defined per-mime-type. these renderers
allow applications to delegate rendering work to the rest of the OS.
there should be a standard function for sniffing MIME types, available
to all applications.
redirects instruct the OS to retry rendering the tab, with a new URI.
the x-pipe mimetype namespace will be used for all bidirectional socket
data, such as a shell session or IRC connection.
x-pipe/shell is reserved for use as a UNIX shell.
x-pipe/ansi is reserved for a pipe which expects a terminal emulator on
on the other end.
x-pipe/text is reserved for use as a pipe of text data.
x-pipe/octet-stream is reserved for use as a generic pipe.
x-pipe/tls is reserved for a pipe which expects the reciever to perform
a TLS handshake immediately.
x-pipe/scheme-* is reserved, and all values of * should correspond to a
wire protocol named *. e.g. x-pipe/scheme-irc indicates
that the pipe is an IRC socket.
the flexible nature of this approach should also allow protocol
handlers to delegate rendering to something else. an app may render its
entire UI as a TUI by returning x-pipe/ansi. the default handler of
x-pipe/ansi MUST ALWAYS be a full-featured terminal emulator.
TODO: define "full-featured"
the default handler of a mime type can be overriden with + in the
scheme. a scheme of the form ssh://server?cmd=cat+/var/www/index.html
would print to the default terminal handler, but
html+ssh://server?cmd=cat+/var/www/index.html would render the file
in the default HTML renderer.
scheme handlers are servers. there should be a directory like
/var/tabbde/schemes, where every file is an executable or a symlink to
an executable. you may have a libcurl-based scheme handler, which is
symlinked to http, https, ftp, ftps, etc. when the WM
encounters an unknown scheme, it will start the corresponding server,
and wait. when a server comes online, it will resume URL processing.
renderers are also servers, with similar semantics, but mapped via
/var/tabbde/mimes.kv, a file mapping MIME glob patterns to renderers
to allow for in-memory lookups.
a cold start for a web browser may look like the following:
1. WM is asked to go to https://example.com
2. WM checks for running https handlers, and finds nonw
3. WM launches /var/tabbde/schemes/https, with the sole argument
https:
4. https connects to the WM, and advertises itself as an https handler
5. WM dispatches the pending https://example.com request
6. https makes the request, and returns data with mimeType text/html,
data a pipe that transparently handles decryption, writable false,
metadata { status: 200, headers: <key-value pairs as string> }
7. WM checks to see what handles text/html, and finds
/path/to/renderer
8. WM executes it, with sole argument text/html
9. renderer connects to the WM, and advertises itself as a text/html
renderer
10. WM dispatches the pending text/html response to the new renderer
the WM will not care about what process or connection an advertisement
comes from, and the most recent advertisement supercedes all others,
meaning that, for example, if a renderer based on a browser engine like
blink were to be used both as an HTML renderer and an XHTML renderer,
and an instance were created for text/html, followed by one for
application/xhtml+xml, the second instance would only need to inform
the first that it should advertise a second mime type, instead of
having two instances resident in memory.
because scheme handlers are initialized with an argument ending in a
colon, and renderers are initialized with an argument like x/y,
a wrapper library's main() should match on either of these, and if
neither are applicable, delegate to some user code. this may be useful
for CLI configuration options.