eBowser — Embedded Web Browser v0.1.0
eBowser is a lightweight, embeddable web browser engine for EmbeddedOS. Built from scratch in C/C++ with minimal dependencies, it provides HTML5 parsing, CSS styling, box-model layout, software rendering, and HTTP/HTTPS networking — all in a footprint suitable for resource-constrained embedded devices, kiosks, and IoT dashboards.
Headers: #include <ebowser/*.h> | License: MIT | Backends: SDL2, EoS native, WASM
Core Engine: Browser lifecycle, configuration, and embedding API.
HTML Parser: Tokenizer → DOM tree construction with error recovery.
CSS Engine: Stylesheet parsing, cascade, specificity, computed styles.
Layout Engine: Box model, block/inline flow, flexbox, text wrapping.
Rendering: Software rasterizer with SDL2 and EoS display backends.
Network: HTTP/1.1, HTTPS (TLS 1.2/1.3), cookies, connection pooling.
Input: Keyboard, mouse, and touch input abstraction with focus management.
Platform: Portable abstraction layer for SDL2, EoS native, and WebAssembly.
#include <ebowser/ebowser.h>
int main(void) {
eb_config_t cfg = {
.width = 1024, .height = 768,
.title = "eBowser",
.flags = EB_FLAG_RESIZABLE
};
eb_handle_t browser = eb_create(&cfg);
eb_navigate(browser, "https://example.com");
eb_run(browser); // blocks until window closed
eb_destroy(browser);
return 0;
}⚙ Core Engine
Browser lifecycle, configuration, and embedding API. Header: <ebowser/ebowser.h>
Configuration
eb_config_t
width | uint32_t | Initial window width in pixels (default: 1024) |
height | uint32_t | Initial window height in pixels (default: 768) |
title | const char * | Window title string |
flags | uint32_t | Bitwise OR of EB_FLAG_* constants |
user_agent | const char * | Custom User-Agent string (NULL = default) |
cache_size_mb | uint32_t | Max cache size in MB (default: 64) |
home_url | const char * | Homepage URL (NULL = about:blank) |
proxy | const char * | HTTP proxy URL (NULL = direct) |
EB_FLAG_RESIZABLE=0x01 • EB_FLAG_FULLSCREEN=0x02 • EB_FLAG_BORDERLESS=0x04 • EB_FLAG_NO_JS=0x08 • EB_FLAG_KIOSK=0x10 • EB_FLAG_HEADLESS=0x20 • EB_FLAG_HARDWARE_ACCEL=0x40Lifecycle
eb_handle_t eb_create(const eb_config_t *config)Create a new browser instance. Initializes the platform backend, rendering surface, and network stack.
Parameters
| config | const eb_config_t * | Browser configuration. Pass NULL for defaults (1024×768, resizable). |
Returns
eb_handle_t browser handle, or EB_INVALID_HANDLE on failure.
Example
eb_config_t cfg = {
.width = 800, .height = 600,
.title = "My Embedded Browser",
.flags = EB_FLAG_RESIZABLE | EB_FLAG_HARDWARE_ACCEL,
.cache_size_mb = 32,
.home_url = "https://example.com"
};
eb_handle_t browser = eb_create(&cfg);
if (browser == EB_INVALID_HANDLE) {
fprintf(stderr, "Failed to create browser\n");
return 1;
}int eb_navigate(eb_handle_t browser, const char *url)Navigate to a URL. Initiates DNS resolution, HTTP request, HTML parsing, layout, and rendering. Non-blocking — the page loads asynchronously.
Parameters
| browser | eb_handle_t | Browser handle. |
| url | const char * | URL to navigate to (http://, https://, file://, or about:). |
Returns
0 on success, negative error code on failure.
Example
eb_navigate(browser, "https://example.com");
eb_navigate(browser, "file:///data/local.html");
eb_navigate(browser, "about:blank");int eb_run(eb_handle_t browser)Enter the main event loop. Processes input events, network I/O, layout updates, and rendering. Blocks until the browser window is closed or eb_stop() is called.
Returns
0 on clean exit.
int eb_step(eb_handle_t browser)Process a single frame of the event loop. Use instead of eb_run() when embedding the browser in a custom event loop.
Returns
1 if running, 0 if exit was requested.
Example
while (eb_step(browser)) {
update_hud();
render_overlay();
}void eb_stop(eb_handle_t browser)Signal the browser to exit the event loop. eb_run() or eb_step() will return on the next iteration.
void eb_destroy(eb_handle_t browser)Destroy a browser instance and free all resources (DOM, stylesheets, network connections, cache, rendering surfaces).
Navigation Control
int eb_go_back(eb_handle_t browser)Navigate to the previous page in history. Returns -1 if no history.
int eb_go_forward(eb_handle_t browser)Navigate to the next page in history. Returns -1 if at the end.
int eb_reload(eb_handle_t browser)Reload the current page. Re-fetches resources from network (respects cache headers).
const char * eb_get_url(eb_handle_t browser)Get the current page URL.
Returns
Current URL string (valid until next navigation).
const char * eb_get_title(eb_handle_t browser)Get the current page title.
eb_load_state_t eb_get_load_state(eb_handle_t browser)Get the current page loading state.
Returns
EB_LOAD_IDLE, EB_LOAD_CONNECTING, EB_LOAD_LOADING, EB_LOAD_RENDERING, or EB_LOAD_COMPLETE.
Callbacks
void eb_set_load_callback(eb_handle_t browser, eb_load_callback_t cb, void *ctx)Register a callback for page load events: void (*)(eb_handle_t, eb_load_state_t state, const char *url, void *ctx)
Example
void on_load(eb_handle_t b, eb_load_state_t state, const char *url, void *ctx) {
if (state == EB_LOAD_COMPLETE)
printf("Page loaded: %s\n", url);
}
eb_set_load_callback(browser, on_load, NULL);void eb_set_navigate_callback(eb_handle_t browser, eb_navigate_callback_t cb, void *ctx)Register a callback invoked before navigation. Return false from the callback to block navigation (URL filtering for kiosk mode). Signature: bool (*)(eb_handle_t, const char *url, void *ctx)
📄 HTML Parser
Tokenizer and DOM tree construction with error recovery. Header: <ebowser/dom.h>
DOM Node Types
eb_dom_node_t
type | eb_node_type_t | ELEMENT, TEXT, COMMENT, DOCUMENT, DOCTYPE |
tag | const char * | Tag name (e.g., "div", "p") — ELEMENT nodes only |
text | const char * | Text content — TEXT and COMMENT nodes |
id | const char * | Element id attribute (or NULL) |
class_name | const char * | Element class attribute (or NULL) |
parent | eb_dom_node_t * | Parent node |
first_child | eb_dom_node_t * | First child node |
next_sibling | eb_dom_node_t * | Next sibling node |
attr_count | uint16_t | Number of attributes |
attrs | eb_attr_t * | Array of name/value attribute pairs |
DOM Query API
eb_dom_node_t * eb_dom_get_document(eb_handle_t browser)Get the root document node of the current page’s DOM tree.
Returns
Root document node, or NULL if no page loaded.
eb_dom_node_t * eb_dom_get_element_by_id(eb_handle_t browser, const char *id)Find the first element with the given id attribute.
Parameters
| browser | eb_handle_t | Browser handle. |
| id | const char * | Element id to search for. |
Returns
Matching element node, or NULL.
Example
eb_dom_node_t *header = eb_dom_get_element_by_id(browser, "main-header");
if (header) printf("Found: <%s id='%s'>\n", header->tag, header->id);eb_dom_node_t ** eb_dom_query_selector_all(eb_handle_t browser, const char *selector, uint32_t *count)Find all elements matching a CSS selector. Supports tag, class, id, attribute, and descendant selectors.
Parameters
| selector | const char * | CSS selector string. |
| count | uint32_t * | Output: number of matches. |
Returns
Array of matching nodes (caller frees with eb_free()).
Example
uint32_t count;
eb_dom_node_t **links = eb_dom_query_selector_all(browser, "a.nav-link", &count);
for (uint32_t i = 0; i < count; i++) {
const char *href = eb_dom_get_attr(links[i], "href");
printf("Link: %s\n", href ? href : "(none)");
}
eb_free(links);eb_dom_node_t * eb_dom_query_selector(eb_handle_t browser, const char *selector)Find the first element matching a CSS selector.
DOM Attribute & Content Access
const char * eb_dom_get_attr(eb_dom_node_t *node, const char *name)Get the value of a named attribute. Returns NULL if not present.
const char * eb_dom_get_text_content(eb_dom_node_t *node)Get concatenated text content of a node and all descendants. Caller frees with eb_free().
const char * eb_dom_get_inner_html(eb_dom_node_t *node)Get serialized HTML of an element’s children. Caller frees with eb_free().
Event Handling
int eb_dom_add_event_listener(eb_dom_node_t *node, const char *event, eb_dom_event_cb_t cb, void *ctx)Attach an event listener to a DOM node.
Parameters
| node | eb_dom_node_t * | Target element. |
| event | const char * | Event name: "click", "input", "submit", "load", "scroll". |
| cb | eb_dom_event_cb_t | void (*)(eb_dom_node_t *target, const eb_dom_event_t *evt, void *ctx) |
| ctx | void * | User context. |
Returns
0 on success.
Example
void on_click(eb_dom_node_t *target, const eb_dom_event_t *evt, void *ctx) {
printf("Clicked: <%s>\n", target->tag);
}
eb_dom_node_t *btn = eb_dom_get_element_by_id(browser, "submit-btn");
eb_dom_add_event_listener(btn, "click", on_click, NULL);🎨 CSS Engine
Stylesheet parsing, cascade, specificity, and computed styles. Header: <ebowser/css.h>
eb_stylesheet_t * eb_css_parse(const char *css_text, size_t len)Parse a CSS string into an internal stylesheet. Supports selectors, properties, media queries, and @-rules.
Returns
Parsed stylesheet, or NULL on failure.
Example
const char *css = "body { background: #fff; color: #333; font-size: 16px; }";
eb_stylesheet_t *sheet = eb_css_parse(css, strlen(css));int eb_css_apply(eb_handle_t browser, eb_stylesheet_t *stylesheet)Apply a stylesheet to the current document. Triggers cascade recalculation and relayout.
Returns
0 on success.
eb_computed_style_t eb_css_computed_style(eb_dom_node_t *node)Get the fully resolved computed style for a DOM element after cascade, specificity, and inheritance.
Example
eb_dom_node_t *el = eb_dom_get_element_by_id(browser, "content");
eb_computed_style_t style = eb_css_computed_style(el);
printf("Font size: %dpx, Color: #%06X\n", style.font_size, style.color);void eb_css_free(eb_stylesheet_t *stylesheet)Free a parsed stylesheet and all associated memory.
Computed Style Structure
eb_computed_style_t
display | eb_display_t | BLOCK, INLINE, FLEX, NONE, INLINE_BLOCK |
color | uint32_t | Text color (0xRRGGBB) |
background_color | uint32_t | Background color (0xRRGGBB) |
font_size | uint16_t | Font size in pixels |
font_weight | uint16_t | Font weight (100-900) |
margin | eb_box_t | Margin (top, right, bottom, left) in px |
padding | eb_box_t | Padding (top, right, bottom, left) in px |
border_width | eb_box_t | Border widths in px |
position | eb_position_t | STATIC, RELATIVE, ABSOLUTE, FIXED |