diff --git a/.github/workflows/ci-debian-build-test.yml b/.github/workflows/ci-debian-build-test.yml index 23483c86..a0d0d434 100644 --- a/.github/workflows/ci-debian-build-test.yml +++ b/.github/workflows/ci-debian-build-test.yml @@ -11,6 +11,10 @@ jobs: fail-fast: false matrix: container: + # sid fails in install build dependencies step + #- image: 'debian:sid' + # env: + # WEBKITGTK_VERSION: '4.1' - image: 'debian:stable' env: WEBKITGTK_VERSION: '4.1' @@ -20,18 +24,18 @@ jobs: - image: 'debian:bullseye' env: WEBKITGTK_VERSION: '4.0' - - image: 'ubuntu:focal' - env: - WEBKITGTK_VERSION: '4.0' - - image: 'debian:sid' - env: - WEBKITGTK_VERSION: '4.1' - image: 'ubuntu:devel' env: WEBKITGTK_VERSION: '4.1' - image: 'ubuntu:noble' env: WEBKITGTK_VERSION: '4.1' + - image: 'ubuntu:jammy' + env: + WEBKITGTK_VERSION: '4.1' + - image: 'ubuntu:focal' + env: + WEBKITGTK_VERSION: '4.0' timeout-minutes: 15 steps: - name: Git checkout diff --git a/src/modes/thread_view/page_client.cc b/src/modes/thread_view/page_client.cc index 9aed8f0a..02570b61 100644 --- a/src/modes/thread_view/page_client.cc +++ b/src/modes/thread_view/page_client.cc @@ -72,11 +72,15 @@ namespace Astroid { LOG (debug) << "pc: closing"; - istream.clear (); - ostream.clear (); + if (ready) { + istream.clear (); + ostream.clear (); - ext->close (); - srv->close (); + ext->close (); + } + if (srv) { + srv->close (); + } } void PageClient::init_web_extensions (WebKitWebContext * context) { diff --git a/src/modes/thread_view/webextension/tvextension.cc b/src/modes/thread_view/webextension/tvextension.cc index 7ddc5135..38f68088 100644 --- a/src/modes/thread_view/webextension/tvextension.cc +++ b/src/modes/thread_view/webextension/tvextension.cc @@ -124,9 +124,14 @@ AstroidExtension::AstroidExtension ( { extension = e; - Glib::init (); + /* initializes glib, gio, gdk, and gtk */ Gtk::Main::init_gtkmm_internals (); - Gio::init (); + /* open the default display */ + if (!Gdk::Display::get_default ()) { + auto display = Gdk::Display::open (""); + g_assert (display); + } + logging::add_common_attributes (); /* load attachment icon */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 106025c2..4b6f3a2c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,4 +53,5 @@ add_astroid_test (dates test_dates test_dates.cc add_astroid_test (crypto test_crypto test_crypto.cc ) add_astroid_test (gmime_version test_gmime_version test_gmime_version.cc ) add_astroid_test (quote_html test_quote_html test_quote_html.cc ) +add_astroid_test (webextension test_webextension test_webextension.cc ) diff --git a/tests/test_webextension.cc b/tests/test_webextension.cc new file mode 100644 index 00000000..e9870180 --- /dev/null +++ b/tests/test_webextension.cc @@ -0,0 +1,161 @@ +# define BOOST_TEST_DYN_LINK +# define BOOST_TEST_MODULE TestWebExtension +# include +# include + +# include + +# include "test_common.hh" + +# include "utils/ustring_utils.hh" + +namespace bfs = boost::filesystem; + +class TestClient : public sigc::trackable +{ +public: + WebKitWebView *webview; + WebKitSettings *websettings; + WebKitWebContext *context; + refptr srv; + refptr ext; + gulong extension_connect_id; + GMainLoop *main_loop; + + void run_loop () + { + LOG (info) << "test: start main loop"; + g_main_loop_run (main_loop); + } + + void quit_loop () + { + LOG (info) << "test: quit main loop"; + g_main_loop_quit (main_loop); + } + + void extension_connect (refptr &res) + { + LOG (info) << "test: got web extension connect"; + ext = refptr::cast_dynamic (srv->accept_finish (res)); + } + + void init_web_extensions (WebKitWebContext * context) + { + bfs::path test_dir = bfs::system_complete (bfs::path (".")); + bfs::path build_dir = test_dir.parent_path (); + BOOST_CHECK (exists (build_dir / bfs::path ("libtvextension.so"))); + + webkit_web_context_set_web_extensions_directory (context, build_dir.c_str ()); + + ustring socket_addr = ustring::compose ("%1/astroid.%2", + test_dir.c_str (), + Astroid::UstringUtils::random_alphanumeric (30)); + refptr addr; + if (Gio::UnixSocketAddress::abstract_names_supported ()) + addr = Gio::UnixSocketAddress::create (socket_addr, + Gio::UNIX_SOCKET_ADDRESS_ABSTRACT); + else + addr = Gio::UnixSocketAddress::create (socket_addr, + Gio::UNIX_SOCKET_ADDRESS_PATH); + + mode_t p = umask (0077); + srv = Gio::SocketListener::create (); + refptr eaddr; + + srv->add_address (addr, Gio::SocketType::SOCKET_TYPE_STREAM, + Gio::SocketProtocol::SOCKET_PROTOCOL_DEFAULT, + eaddr); + + srv->accept_async (sigc::mem_fun (this, &TestClient::extension_connect)); + umask (p); + + GVariant *gaddr = g_variant_new_string (addr->get_path ().c_str ()); + webkit_web_context_set_web_extensions_initialization_user_data (context, gaddr); + } + + static void on_web_extensions (WebKitWebContext *context, GVariant *user_data) + { + LOG (info) << "test: called initialize-web-extensions"; + ((TestClient *) user_data)->init_web_extensions (context); + } + + static void on_load_changed (WebKitWebView *webview, + WebKitLoadEvent load_event, + TestClient *test) + { + LOG (info) << "test: called load-changed"; + if (load_event != WEBKIT_LOAD_FINISHED) + return; + g_signal_handlers_disconnect_by_func (webview, + (gpointer) TestClient::on_load_changed, + test); + test->quit_loop (); + } + + static gboolean wait_failed (gpointer user_data) + { + bool wait_timed_out = false; + ((TestClient *) user_data)->quit_loop (); + BOOST_CHECK (wait_timed_out); + return G_SOURCE_REMOVE; + } + + void wait (double seconds) + { + g_timeout_add (seconds * 1000, TestClient::wait_failed, this); + g_signal_connect (webview, "load-changed", + G_CALLBACK (TestClient::on_load_changed), + (gpointer) this); + run_loop (); + } + + TestClient () + { + context = webkit_web_context_new_ephemeral (); + extension_connect_id = g_signal_connect (context, + "initialize-web-extensions", + G_CALLBACK (TestClient::on_web_extensions), + (gpointer) this); + main_loop = g_main_loop_new (nullptr, true); + + websettings = WEBKIT_SETTINGS (webkit_settings_new_with_settings (NULL)); + + webview = WEBKIT_WEB_VIEW (g_object_new (WEBKIT_TYPE_WEB_VIEW, + "web-context", context, + "settings", websettings, + NULL)); + + if (g_object_is_floating (webview)) + g_object_ref_sink (webview); + + webkit_web_view_load_html (webview, + "WebExtension", + Astroid::UstringUtils::random_alphanumeric (30).c_str ()); + } + + ~TestClient () + { + g_signal_handler_disconnect (context, extension_connect_id); + if (ext) ext->close (); + if (srv) srv->close (); + g_object_unref (context); + g_object_unref (websettings); + g_object_unref (webview); + } +}; + +BOOST_AUTO_TEST_SUITE(WebExtension) + + BOOST_AUTO_TEST_CASE(page_client) + { + setup (); + + auto client = new TestClient (); + client->wait (10); + delete client; + + teardown (); + } + +BOOST_AUTO_TEST_SUITE_END()