diff options
| author | Akshay Nair <phenax5@gmail.com> | 2025-05-01 22:21:48 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2025-05-02 16:20:48 +0530 |
| commit | 86496d0ce96f2e57f3f301c08488b6421321b3c9 (patch) | |
| tree | 2dd20f110c0eec27748b94e6fb84f19fb85ba6d0 | |
| parent | fab5f4d2fd80eb288265c64ba390460ac974ee81 (diff) | |
| download | null-browser-86496d0ce96f2e57f3f301c08488b6421321b3c9.tar.gz null-browser-86496d0ce96f2e57f3f301c08488b6421321b3c9.zip | |
Add PermissionRequested event and accept/reject handling
| -rw-r--r-- | TODO.org | 5 | ||||
| -rw-r--r-- | init.lua | 19 | ||||
| -rw-r--r-- | lua/null-browser/defaults/vi.lua | 9 | ||||
| -rw-r--r-- | lua/null-browser/stdlib.lua | 3 | ||||
| -rw-r--r-- | src/events.hpp | 110 | ||||
| -rw-r--r-- | src/widgets/WebViewStack.cpp | 24 | ||||
| -rw-r--r-- | src/widgets/WebViewStack.hpp | 1 |
7 files changed, 147 insertions, 24 deletions
@@ -9,8 +9,9 @@ - [X] Scroll api (for j/k/h/l/gg/G) - [X] table extend/merge - [X] window.opener controls (use tab for now?) -- [ ] Tests for api -- [ ] Permission requests handling/persisting +- [X] Permission requests handling +- [-] Tests for api +- [ ] Permission requests persist - [ ] Notifications - [ ] Fullscreen - [ ] Zoom in/out @@ -2,7 +2,7 @@ print('hello starting up...') web.set('new_view_url', 'https://lite.duckduckgo.com') web.set('close_window_when_no_views', true) -web.set('user_agent', 'MacOS | Safari - $500 edition') +-- web.set('user_agent', 'MacOS | Safari - $500 edition') web.set('downloads_dir', os.getenv('HOME') .. '/Downloads/firefox') local dmenu = require 'null-browser.extras.dmenu' @@ -16,7 +16,22 @@ search_engines.urls['ld'] = 'https://lite.duckduckgo.com/?q={}' require 'null-browser.defaults.vi'.setup { menu = dmenu, history = history, - preprocess_url = search_engines.preprocess_url, + transform_url_input = search_engines.transform_url_input, } +web.event.add_listener('PermissionRequested', { + callback = function(event) + dmenu.select({ 'Allow', 'Deny' }, { prompt = 'Requesting permission for ' .. event.permission_type }, + function(err, choice) + if err then return print('-- x permission ignored') end + print('----- permission', event.permission_type, web.inspect(choice)) + if web.utils.string_trim(choice) == 'Allow' then + event.accept() + else + event.reject() + end + end) + end, +}) + print('ending...') diff --git a/lua/null-browser/defaults/vi.lua b/lua/null-browser/defaults/vi.lua index 1b72f60..cefbbd2 100644 --- a/lua/null-browser/defaults/vi.lua +++ b/lua/null-browser/defaults/vi.lua @@ -1,11 +1,11 @@ local M = {} + local config = { menu = require 'null-browser.extras.dmenu', history = require 'null-browser.extras.history', - preprocess_url = web.utils.string_trim, + transform_url_input = web.utils.string_trim, } - function M.setup(opts) config = web.utils.table_merge(config, opts) end @@ -26,17 +26,16 @@ function M.initialize() -- Open in new view web.keymap.set('n', 'o', function() - print(web.get('new_view_url'), web.get('user_agent')) config.menu.select(config.history.list(), { prompt = 'Open view:' }, function(err, result) if err or not result then return end - web.view.create(config.preprocess_url(result)) + web.view.create(config.transform_url_input(result)) end) end) -- Open in current view web.keymap.set('n', '<s-o>', function() config.menu.select(config.history.list(), { prompt = 'Open:' }, function(err, result) if err or not result then return end - web.view.set_url(config.preprocess_url(result)) + web.view.set_url(config.transform_url_input(result)) end) end) -- Delete from history diff --git a/lua/null-browser/stdlib.lua b/lua/null-browser/stdlib.lua index f96dd48..737f747 100644 --- a/lua/null-browser/stdlib.lua +++ b/lua/null-browser/stdlib.lua @@ -7,6 +7,9 @@ local inspector_loaded, inspector = pcall(require, 'inspect') if inspector_loaded then web.inspect = inspector.inspect else + --- Returns human-readable string representation of Lua tables + --- + --- @link https://github.com/kikito/inspect.lua web.inspect = function(val) print('[warn] "inspect" module not loaded'); return val end diff --git a/src/events.hpp b/src/events.hpp index ffa4f8b..f16c2a1 100644 --- a/src/events.hpp +++ b/src/events.hpp @@ -1,8 +1,12 @@ #pragma once #include <QtCore> +#include <functional> #include <lua.hpp> +#include <memory> +#include <qwebenginepermission.h> +#include "LuaRuntime.hpp" #include "lua.h" #include "widgets/BrowserWindow.hpp" #include "widgets/WebViewStack.hpp" @@ -15,30 +19,126 @@ class BrowserEvent { public: QString kind = "-"; - virtual ~BrowserEvent() = default; - virtual void lua_push(lua_State *state) const { lua_newtable(state); }; + virtual void lua_push(lua_State *state) const { + lua_newtable(state); + SET_FIELD("type", string, kind.toStdString().c_str()) + }; }; class UrlChangedEvent : public BrowserEvent { public: - const QString url; + const QString &url; const WebViewId webview_id; const WindowId win_id; - UrlChangedEvent(QString url, WebViewId webview_id, WindowId win_id) - : url(std::move(url)), webview_id(webview_id), win_id(win_id) { + UrlChangedEvent(const QString &url, WebViewId webview_id, WindowId win_id) + : url(url), webview_id(webview_id), win_id(win_id) { kind = "UrlChanged"; } void lua_push(lua_State *state) const override { lua_newtable(state); + SET_FIELD("type", string, kind.toStdString().c_str()) SET_FIELD("view_id", integer, webview_id) SET_FIELD("win_id", integer, win_id) SET_FIELD("url", string, url.toStdString().c_str()) } }; +class PermissionRequestEvent : public BrowserEvent { +public: + const QWebEnginePermission::PermissionType premission_type; + const WebViewId webview_id; + const WindowId win_id; + std::function<void()> accept_request; + std::function<void()> reject_request; + + PermissionRequestEvent(QWebEnginePermission::PermissionType type, + std::function<void()> accept_request, std::function<void()> reject_request, + WebViewId webview_id, WindowId win_id) + : premission_type(type), webview_id(webview_id), win_id(win_id), + accept_request(std::move(accept_request)), reject_request(std::move(reject_request)) { + kind = "PermissionRequested"; + } + + static PermissionRequestEvent *from_permission(std::shared_ptr<QWebEnginePermission> &permission, + WebViewId webview_id, WindowId win_id) { + auto accept = [permission]() { + QMetaObject::invokeMethod(qApp, [=]() { permission->grant(); }, Qt::QueuedConnection); + }; + auto reject = [permission]() { + QMetaObject::invokeMethod(qApp, [=]() { permission->deny(); }, Qt::QueuedConnection); + }; + // TODO: Manage delete for permission object + return new PermissionRequestEvent(permission->permissionType(), accept, reject, webview_id, + win_id); + } + + [[nodiscard]] const char *permission_type() const { + switch (premission_type) { + case QWebEnginePermission::PermissionType::MediaAudioCapture: + return "MediaAudioCapture"; + case QWebEnginePermission::PermissionType::MediaVideoCapture: + return "MediaVideoCapture"; + case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: + return "MediaAudioVideoCapture"; + case QWebEnginePermission::PermissionType::DesktopVideoCapture: + return "DesktopVideoCapture"; + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: + return "DesktopAudioVideoCapture"; + case QWebEnginePermission::PermissionType::MouseLock: + return "MouseLock"; + case QWebEnginePermission::PermissionType::Notifications: + return "Notifications"; + case QWebEnginePermission::PermissionType::Geolocation: + return "Geolocation"; + case QWebEnginePermission::PermissionType::ClipboardReadWrite: + return "ClipboardReadWrite"; + case QWebEnginePermission::PermissionType::LocalFontsAccess: + return "LocalFontsAccess"; + default: + return "Unsupported"; + } + } + + void lua_push(lua_State *state) const override { + lua_newtable(state); + SET_FIELD("type", string, kind.toStdString().c_str()) + SET_FIELD("permission_type", string, permission_type()) + SET_FIELD("view_id", integer, webview_id) + SET_FIELD("win_id", integer, win_id) + + lua_pushstring(state, "accept"); + lua_pushlightuserdata(state, (void *)this); + lua_pushcclosure( + state, + [](lua_State *state) { + void *userdata = lua_touserdata(state, lua_upvalueindex(1)); + auto *event = static_cast<PermissionRequestEvent *>(userdata); + event->accept_request(); + lua_pushnil(state); + return 1; + }, + 1); + lua_settable(state, -3); + + lua_pushstring(state, "reject"); + lua_pushlightuserdata(state, (void *)this); + lua_pushcclosure( + state, + [](lua_State *state) { + void *userdata = lua_touserdata(state, lua_upvalueindex(1)); + auto *event = static_cast<PermissionRequestEvent *>(userdata); + event->reject_request(); + lua_pushnil(state); + return 1; + }, + 1); + lua_settable(state, -3); + } +}; + struct EventHandlerRequest { std::vector<QString> event_names; std::vector<QString> patterns; diff --git a/src/widgets/WebViewStack.cpp b/src/widgets/WebViewStack.cpp index c48a363..7fe9218 100644 --- a/src/widgets/WebViewStack.cpp +++ b/src/widgets/WebViewStack.cpp @@ -5,6 +5,7 @@ #include <QWebEngineProfile> #include <cstdint> #include <cstdlib> +#include <memory> #include <vector> #include "WindowActionRouter.hpp" @@ -48,17 +49,22 @@ WebView *WebViewStack::create_new_webview(const QUrl &url, bool focus) { layout->addWidget(webview); webview_list.append(webview); - connect(webview->page(), &QWebEnginePage::newWindowRequested, this, - &WebViewStack::on_new_webview_request); - connect(webview->page(), &QWebEnginePage::urlChanged, this, [webview](const QUrl &url) { + auto *page = webview->page(); + connect(page, &QWebEnginePage::newWindowRequested, this, &WebViewStack::on_new_webview_request); + connect(page, &QWebEnginePage::urlChanged, this, [webview](const QUrl &url) { // TODO: Add window id - WindowActionRouter::instance().dispatch_event( - new UrlChangedEvent(url.toString(), webview->get_id(), 0)); + auto *event = new UrlChangedEvent(url.toString(), webview->get_id(), 0); + WindowActionRouter::instance().dispatch_event(event); + }); + connect(page, &QWebEnginePage::titleChanged, this, [this](const QString & /* title */) { + emit current_webview_title_changed(layout->currentIndex()); + }); + connect(page, &QWebEnginePage::permissionRequested, this, [webview](QWebEnginePermission perm) { + auto permission = std::make_shared<QWebEnginePermission>(std::move(perm)); + // TODO: Add windown id + auto *event = PermissionRequestEvent::from_permission(permission, webview->get_id(), 0); + WindowActionRouter::instance().dispatch_event(event); }); - connect(webview->page(), &QWebEnginePage::titleChanged, this, - [this](const QString & /* title */) { - emit current_webview_title_changed(layout->currentIndex()); - }); if (focus) focus_webview(webview->get_id()); diff --git a/src/widgets/WebViewStack.hpp b/src/widgets/WebViewStack.hpp index 1b8b288..cee0593 100644 --- a/src/widgets/WebViewStack.hpp +++ b/src/widgets/WebViewStack.hpp @@ -3,7 +3,6 @@ #include <QStackedLayout> #include <QWebEngineProfile> #include <cstdint> -#include <functional> #include <qwebengineprofile.h> #include <vector> |
