diff options
| author | Akshay Nair <phenax5@gmail.com> | 2025-05-02 12:04:43 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2025-05-02 16:24:38 +0530 |
| commit | 398b1a4b398324311b6e0f15d2e4ede5ad8500ff (patch) | |
| tree | 4af9a1b5106dc30d22adc0a4391b5ac006dd7141 | |
| parent | 8a71de53c002b7afdd516cff7190896d40496483 (diff) | |
| download | null-browser-398b1a4b398324311b6e0f15d2e4ede5ad8500ff.tar.gz null-browser-398b1a4b398324311b6e0f15d2e4ede5ad8500ff.zip | |
Prefix uv with web.uv + add permissions_persistance config option
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | TODO.org | 10 | ||||
| -rw-r--r-- | flake.lock | 6 | ||||
| -rw-r--r-- | init.lua | 3 | ||||
| -rw-r--r-- | lua/null-browser/extras/dmenu.lua | 19 | ||||
| -rw-r--r-- | lua/null-browser/extras/history.lua | 14 | ||||
| -rw-r--r-- | lua/null-browser/utils.lua | 6 | ||||
| -rw-r--r-- | src/Configuration.hpp | 22 | ||||
| -rw-r--r-- | src/LuaRuntime.cpp | 7 | ||||
| -rw-r--r-- | src/LuaRuntime.hpp | 3 | ||||
| -rw-r--r-- | src/WindowActionRouter.cpp | 5 | ||||
| -rw-r--r-- | src/WindowMediator.cpp | 6 | ||||
| -rw-r--r-- | src/WindowMediator.hpp | 1 | ||||
| -rw-r--r-- | src/main.cpp | 2 | ||||
| -rw-r--r-- | src/widgets/BrowserApp.cpp | 3 | ||||
| -rw-r--r-- | src/widgets/BrowserWindow.cpp | 4 |
16 files changed, 71 insertions, 42 deletions
@@ -27,6 +27,8 @@ This web browser is just a stack of web views that can be controlled using lua. - filter host-names - **No settings page** - write some lua +- **No incognito/private window** + - create a window with a custom user data directory and delete it when window is closed - **No chromium/web extensions** - inject javascript into pages from your lua config - **No built-in cryptocurrency** @@ -1,20 +1,19 @@ ** Usable - [-] Tests for api -- [ ] Config permission persist (persist_permission_state = 'always' | 'never' | 'in_memory') - [ ] Permission list/allow/deny api - [ ] Fullscreen - [ ] Zoom in/out - [ ] Run JS in page (web.view.eval_js()) - [ ] Use table for all internals api options? - [ ] Create window with new profile +- [ ] User data/profiles management ** Bugs -- [ ] INVESTIGATE: segfault on api module error -- [ ] INVESTIGATE: Check why urlchanged doesnt fire for first url open -- [ ] INVESTIGATE: Segfault on close -- [ ] INVESTIGATE: Errors in keymap/thread segfaults +- [ ] INVESTIGATE: Check why urlchanged doesnt fire for first url open sometimes +- [ ] INVESTIGATE: Segfault on close sometimes ** Next +- [ ] Configuration validation - [ ] web.win.* apis (list, current_id) - [ ] Allow toggling devtools - [ ] Tests for window @@ -26,7 +25,6 @@ - [ ] Allow pattern filtering for event listeners - [ ] Allow tab_id, win_id filtering for event listeners - [ ] Handle resource cleanup + signal disconnecting -- [ ] Profiles - [ ] Private window (in-memory profile) - [ ] Read page contents via lua @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1744868846, - "narHash": "sha256-5RJTdUHDmj12Qsv7XOhuospjAjATNiTMElplWnJE9Hs=", + "lastModified": 1745377448, + "narHash": "sha256-jhZDfXVKdD7TSEGgzFJQvEEZ2K65UMiqW5YJ2aIqxMA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ebe4301cbd8f81c4f8d3244b3632338bbeb6d49c", + "rev": "507b63021ada5fee621b6ca371c4fca9ca46f52c", "type": "github" }, "original": { @@ -20,6 +20,7 @@ require 'null-browser.defaults.vi'.setup { transform_url_input = search_engines.transform_url_input, } +-- web.set('permissions_persistance', 'never') web.event.add_listener('PermissionRequested', { callback = function(event) dmenu.select({ 'Allow', 'Deny' }, { prompt = 'Requesting permission for ' .. event.permission_type }, @@ -38,7 +39,7 @@ web.event.add_listener('NotificationReceived', { callback = function(event) -- TODO: Add action/click (-A) local args = { '-a', 'null-browser', '-r', event.tag, event.title, event.message } - uv.spawn('notify-send', { args = args }, function(code) + web.uv.spawn('notify-send', { args = args }, function(code) if code ~= 0 then print('[notify-send] Exit with status code: ' .. code) end diff --git a/lua/null-browser/extras/dmenu.lua b/lua/null-browser/extras/dmenu.lua index c7a941f..fc92b35 100644 --- a/lua/null-browser/extras/dmenu.lua +++ b/lua/null-browser/extras/dmenu.lua @@ -1,12 +1,9 @@ ---- @type table -uv = uv - local dmenu = {} function dmenu.select(list, opts, callback) local selection = nil - local stdin = uv.new_pipe(); - local stdout = uv.new_pipe(); + local stdin = web.uv.new_pipe(); + local stdout = web.uv.new_pipe(); local args = opts.args or {} if opts.prompt then table.insert(args, '-p') @@ -17,9 +14,9 @@ function dmenu.select(list, opts, callback) table.insert(args, opts.input) end - uv.spawn('dmenu', { args = args, stdio = { stdin, stdout, nil } }, function(code) - uv.close(stdout) - uv.close(stdin) + web.uv.spawn('dmenu', { args = args, stdio = { stdin, stdout, nil } }, function(code) + web.uv.close(stdout) + web.uv.close(stdin) if code == 0 then callback(nil, selection) else @@ -27,14 +24,14 @@ function dmenu.select(list, opts, callback) end end) - uv.read_start(stdout, function(_, data) + web.uv.read_start(stdout, function(_, data) if data then selection = data end end) for _, value in ipairs(list) do - uv.write(stdin, value .. '\n') + web.uv.write(stdin, value .. '\n') end - uv.shutdown(stdin) + web.uv.shutdown(stdin) end function dmenu.input(opts, callback) diff --git a/lua/null-browser/extras/history.lua b/lua/null-browser/extras/history.lua index 8106178..d1f58d0 100644 --- a/lua/null-browser/extras/history.lua +++ b/lua/null-browser/extras/history.lua @@ -6,11 +6,11 @@ local history = { local hook_registered = false function history.list() - local file = uv.fs_open(history.path, 'r', 438) + local file = web.uv.fs_open(history.path, 'r', 438) if not file then return {} end - local stat = assert(uv.fs_fstat(file)) - local data = assert(uv.fs_read(file, stat.size)) - assert(uv.fs_close(file)) + local stat = assert(web.uv.fs_fstat(file)) + local data = assert(web.uv.fs_read(file, stat.size)) + assert(web.uv.fs_close(file)) local urls = {} for line in string.gmatch(data, '[^\r\n]+') do @@ -33,11 +33,11 @@ end function history.update(func) local urls = history.list() - local file = assert(uv.fs_open(history.path, 'w', 438)) + local file = assert(web.uv.fs_open(history.path, 'w', 438)) urls = func(urls) local contents = table.concat(urls, '\n') - assert(uv.fs_write(file, contents)) - assert(uv.fs_close(file)) + assert(web.uv.fs_write(file, contents)) + assert(web.uv.fs_close(file)) end function history.add(url) diff --git a/lua/null-browser/utils.lua b/lua/null-browser/utils.lua index b6ff40a..2fe44e1 100644 --- a/lua/null-browser/utils.lua +++ b/lua/null-browser/utils.lua @@ -2,6 +2,12 @@ _G.web = _G.web or {} web.utils = web.utils or {} +--- luv api +--- @type table +--- @link https://github.com/luvit/luv/blob/master/docs.md +--- @diagnostic disable-next-line: undefined-global +web.uv = web.uv or nil + local inspector = require 'null-browser.inspect' --- Returns human-readable string representation of Lua tables diff --git a/src/Configuration.hpp b/src/Configuration.hpp index 1f861fa..7c97b72 100644 --- a/src/Configuration.hpp +++ b/src/Configuration.hpp @@ -15,6 +15,7 @@ private: {"user_agent", QWebEngineProfile::defaultProfile()->httpUserAgent()}, {"downloads_dir", QWebEngineProfile::defaultProfile()->downloadPath()}, {"app_data_dir", QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)}, + {"permissions_persistance", "always"}, }; QDir config_dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)); @@ -42,6 +43,22 @@ public: QString new_view_url() const { return get_config("new_view_url").toString(); } QString user_agent() const { return get_config("user_agent").toString(); } QString downloads_dir() const { return get_config("downloads_dir").toString(); } + QString permissions_persistance() const { + return get_config("permissions_persistance").toString(); + } + + QWebEngineProfile::PersistentPermissionsPolicy permission_persistance_policy() const { + return to_permission_persistance_policy(permissions_persistance()); + } + + static QWebEngineProfile::PersistentPermissionsPolicy + to_permission_persistance_policy(const QString &persistance) { + if (persistance == "session") + return QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory; + if (persistance == "never") + return QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime; + return QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk; + } DEFINE_GETTER(get_config_dir, config_dir) DEFINE_SETTER(set_config_dir, config_dir) @@ -53,11 +70,14 @@ private: void on_update(const QString &name, const QVariant &value) { if (name == "user_agent") emit user_agent_updated(value.toString()); - if (name == "downloads_dir") + else if (name == "downloads_dir") emit downloads_dir_updated(value.toString()); + else if (name == "permissions_persistance") + emit permissions_persistance_updated(value.toString()); } signals: void user_agent_updated(const QString &value); void downloads_dir_updated(const QString &value); + void permissions_persistance_updated(const QString &value); }; diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp index 07ddb67..e9dc86f 100644 --- a/src/LuaRuntime.cpp +++ b/src/LuaRuntime.cpp @@ -35,7 +35,8 @@ void LuaRuntime::start_event_loop() { luv_set_loop(state, event_loop->get_uv_loop()); luv_set_callback(state, &luv_callback); luaopen_luv(state); - lua_setglobal(state, uv_global_name); + lua_setglobal(state, "uv"); + luaL_dostring(state, "web.uv = uv"); } void LuaRuntime::stop_event_loop() { @@ -46,13 +47,13 @@ void LuaRuntime::stop_event_loop() { // Clear the uv global lua_pushnil(state); - lua_setglobal(state, uv_global_name); + lua_setglobal(state, "uv"); lua_gc(state, LUA_GCCOLLECT, 0); } void LuaRuntime::init_web_api() { luaL_newlib(state, internals_api); - lua_setglobal(state, internals_global_name); + lua_setglobal(state, "__internals"); require_module("null-browser.api"); } diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp index 2af61f7..527501e 100644 --- a/src/LuaRuntime.hpp +++ b/src/LuaRuntime.hpp @@ -23,9 +23,6 @@ class LuaRuntime : public QObject { Q_OBJECT - const char *uv_global_name = "uv"; - const char *internals_global_name = "__internals"; - public: static LuaRuntime &instance() { static LuaRuntime runtime; diff --git a/src/WindowActionRouter.cpp b/src/WindowActionRouter.cpp index 721a3e7..7270855 100644 --- a/src/WindowActionRouter.cpp +++ b/src/WindowActionRouter.cpp @@ -34,6 +34,11 @@ void WindowActionRouter::initialize(Configuration *config) { for (auto &win_match : window_map) win_match.second->mediator()->update_downloads_dir(downloads_dir); }); + connect(configuration, &Configuration::permissions_persistance_updated, this, + [this](const QString &persistance) { + for (auto &win_match : window_map) + win_match.second->mediator()->update_permissions_persistance(persistance); + }); // History connect(&runtime, &LuaRuntime::history_back_requested, this, diff --git a/src/WindowMediator.cpp b/src/WindowMediator.cpp index cb677ee..fa9a25e 100644 --- a/src/WindowMediator.cpp +++ b/src/WindowMediator.cpp @@ -23,6 +23,12 @@ void WindowMediator::update_downloads_dir(const QString &downloads_dir) { profile->setDownloadPath(downloads_dir); } +void WindowMediator::update_permissions_persistance(const QString &persistance) { + auto *profile = webview_stack->get_profile(); + auto persistance_policy = Configuration::to_permission_persistance_policy(persistance); + profile->setPersistentPermissionsPolicy(persistance_policy); +} + WindowMediator::~WindowMediator() { disconnect(this); delete webview_stack; diff --git a/src/WindowMediator.hpp b/src/WindowMediator.hpp index 0a27f2e..163ab7a 100644 --- a/src/WindowMediator.hpp +++ b/src/WindowMediator.hpp @@ -34,6 +34,7 @@ signals: public slots: void update_user_agent(const QString &user_agent); void update_downloads_dir(const QString &downloads_dir); + void update_permissions_persistance(const QString &persistance); private: WebViewStack *webview_stack; diff --git a/src/main.cpp b/src/main.cpp index dc67c8a..ee94ad3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,7 @@ QCommandLineParser *create_cli_parser() { parser->addPositionalArgument("url", "URL(s) to open", "[url]"); parser->addOptions({ {{"e", "expr"}, "Lua expression to execute", "lua"}, - {{"c", "config-dir"}, "Config directory for null browser", "dir"}, + {{"C", "config-dir"}, "Config directory for null browser", "dir"}, }); return parser; diff --git a/src/widgets/BrowserApp.cpp b/src/widgets/BrowserApp.cpp index 32ac598..54fd44a 100644 --- a/src/widgets/BrowserApp.cpp +++ b/src/widgets/BrowserApp.cpp @@ -41,8 +41,7 @@ BrowserApp::BrowserApp(Configuration &configuration) : configuration(configurati auto *event = new NotificationReceivedEvent(std::move(notification)); WindowActionRouter::instance().dispatch_event(event); }); - profile->setPersistentPermissionsPolicy( - QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory); + profile->setPersistentPermissionsPolicy(configuration.permission_persistance_policy()); } connect(&window_action_router, &WindowActionRouter::new_window_requested, this, diff --git a/src/widgets/BrowserWindow.cpp b/src/widgets/BrowserWindow.cpp index d1b9c44..8e1555f 100644 --- a/src/widgets/BrowserWindow.cpp +++ b/src/widgets/BrowserWindow.cpp @@ -22,10 +22,6 @@ BrowserWindow::BrowserWindow(const Configuration &configuration, QWebEngineProfi layout->setSpacing(0); centralWidget()->setLayout(layout); - // Webengine profile - profile->setDownloadPath(configuration.downloads_dir()); - profile->setHttpUserAgent(configuration.user_agent()); - // Stack of web views auto *webview_stack = new WebViewStack(&configuration, profile); layout->addWidget(webview_stack); |
