From d8ef8e68805ab7f53258427c79ee5aaafec916ba Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 10 Mar 2016 17:09:59 -0600 Subject: add UsbManager --- src/usb-manager.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/usb-manager.cpp (limited to 'src/usb-manager.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp new file mode 100644 index 0000000..6b40cea --- /dev/null +++ b/src/usb-manager.cpp @@ -0,0 +1,109 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +class UsbManager::Impl +{ +public: + + explicit Impl( + const std::string& socket_path, + const std::string& public_keys_filename + ): + m_adbd_client{std::make_shared(socket_path)}, + m_public_keys_filename{public_keys_filename} + { + m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ + auto snap = new UsbSnap(req.fingerprint); + snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool /*FIXME: remember_choice*/){ + req.respond(response); + if (response == AdbdClient::PKResponse::ALLOW) + write_public_key(req.public_key); + + // delete later + g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); + }); + }); + } + + ~Impl() + { + } + +private: + + void write_public_key(const std::string& public_key) + { + // confirm the directory exists + auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); + const auto dir_exists = g_file_test(dirname, G_FILE_TEST_IS_DIR); + if (!dir_exists) + g_warning("ADB data directory '%s' does not exist", dirname); + g_clear_pointer(&dirname, g_free); + if (!dir_exists) + return; + + // open the file in append mode, with user rw and group r permissions + const auto fd = open( + m_public_keys_filename.c_str(), + O_APPEND|O_CREAT|O_WRONLY, + S_IRUSR|S_IWUSR|S_IRGRP + ); + if (fd == -1) { + g_warning("Error opening ADB datafile: %s", g_strerror(errno)); + return; + } + + // write the new public key on its own line + std::string buf {public_key + '\n'}; + if (write(fd, buf.c_str(), buf.size()) == -1) + g_warning("Error writing ADB datafile: %d %s", errno, g_strerror(errno)); + close(fd); + } + + std::shared_ptr m_adbd_client; + const std::string m_public_keys_filename; +}; + +/*** +**** +***/ + +UsbManager::UsbManager( + const std::string& socket_path, + const std::string& public_keys_filename +): + impl{new Impl{socket_path, public_keys_filename}} +{ +} + +UsbManager::~UsbManager() +{ +} + -- cgit v1.2.3 From 078459b6c837264eb2d6b45a84a1641a3aeab2cc Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Mar 2016 09:04:26 -0500 Subject: in usb-manager.cpp, remove the remember_choice workaround since is already working around it --- src/usb-manager.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/usb-manager.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 6b40cea..f089a22 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -41,12 +41,11 @@ public: { m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ auto snap = new UsbSnap(req.fingerprint); - snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool /*FIXME: remember_choice*/){ + snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ req.respond(response); - if (response == AdbdClient::PKResponse::ALLOW) + if (remember_choice) write_public_key(req.public_key); - - // delete later + // delete_later g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); }); }); -- cgit v1.2.3 From ccecdd46da33ff51b2d45528439de09fe87a393c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 18 Mar 2016 10:42:41 -0500 Subject: add some extra debug statements to usb-manager.cpp to track user response and the act of writing the pk out to disk --- src/usb-manager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/usb-manager.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index f089a22..335db00 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -42,8 +42,9 @@ public: m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ auto snap = new UsbSnap(req.fingerprint); snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("user responded! response %d, remember %d", int(response), int(remember_choice)); req.respond(response); - if (remember_choice) + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) write_public_key(req.public_key); // delete_later g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); @@ -59,6 +60,8 @@ private: void write_public_key(const std::string& public_key) { + g_debug("writing public key '%s' to '%s'", public_key.c_str(), m_public_keys_filename.c_str()); + // confirm the directory exists auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); const auto dir_exists = g_file_test(dirname, G_FILE_TEST_IS_DIR); -- cgit v1.2.3 From 45709c48f34e0909c1309dccac1dd3e047f518fb Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 18 Mar 2016 12:39:58 -0500 Subject: turn off verbose debugging --- src/main.cpp | 3 --- src/usb-manager.cpp | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src/usb-manager.cpp') diff --git a/src/main.cpp b/src/main.cpp index 2e428f9..7d6eb5f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,9 +29,6 @@ int main(int /*argc*/, char** /*argv*/) { -#warning NB the next line turns on verbose debug logging and is used for developement. Remove it before landing. -g_assert(g_setenv("G_MESSAGES_DEBUG", "all", true)); - // Work around a deadlock in glib's type initialization. // It can be removed when https://bugzilla.gnome.org/show_bug.cgi?id=674885 is fixed. g_type_ensure(G_TYPE_DBUS_CONNECTION); diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 335db00..7f43520 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -42,7 +42,7 @@ public: m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ auto snap = new UsbSnap(req.fingerprint); snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("user responded! response %d, remember %d", int(response), int(remember_choice)); + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); req.respond(response); if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) write_public_key(req.public_key); @@ -78,12 +78,12 @@ private: S_IRUSR|S_IWUSR|S_IRGRP ); if (fd == -1) { - g_warning("Error opening ADB datafile: %s", g_strerror(errno)); + g_warning("Error opening ADB datafile '%s': %s", m_public_keys_filename.c_str(), g_strerror(errno)); return; } // write the new public key on its own line - std::string buf {public_key + '\n'}; + const std::string buf {public_key + '\n'}; if (write(fd, buf.c_str(), buf.size()) == -1) g_warning("Error writing ADB datafile: %d %s", errno, g_strerror(errno)); close(fd); -- cgit v1.2.3 From 7a25132c125f6e5e413ad26ea950ae22bee982f5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 21 Mar 2016 13:40:11 -0500 Subject: if our USB device is disconnected while prompting the user for ADBD, cancel the prompt. --- CMakeLists.txt | 1 + debian/control | 1 + src/CMakeLists.txt | 1 + src/adbd-client.cpp | 1 + src/main.cpp | 4 +- src/usb-manager.cpp | 63 +++++++++++++++++--------- src/usb-manager.h | 11 ++++- src/usb-monitor.cpp | 81 ++++++++++++++++++++++++++++++++++ src/usb-monitor.h | 52 ++++++++++++++++++++++ src/usb-snap.cpp | 1 + tests/integration/usb-manager-test.cpp | 44 ++++++++++++++++-- tests/unit/usb-snap-test.cpp | 1 - tests/utils/mock-usb-monitor.h | 32 ++++++++++++++ tests/utils/qdbus-helpers.h | 21 --------- tests/utils/qt-fixture.h | 18 +++++++- 15 files changed, 284 insertions(+), 48 deletions(-) create mode 100644 src/usb-monitor.cpp create mode 100644 src/usb-monitor.h create mode 100644 tests/utils/mock-usb-monitor.h delete mode 100644 tests/utils/qdbus-helpers.h (limited to 'src/usb-manager.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index bb7568e..8a1a6aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ set(GLIB_MINIMUM 2.36) pkg_check_modules(SERVICE_DEPS REQUIRED gio-unix-2.0>=${GLIB_MINIMUM} glib-2.0>=${GLIB_MINIMUM} + gudev-1.0 ) include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS} diff --git a/debian/control b/debian/control index 529fa37..90e2590 100644 --- a/debian/control +++ b/debian/control @@ -7,6 +7,7 @@ Build-Depends: cmake, cmake-extras (>= 0.4), dbus, libglib2.0-dev (>= 2.36), + libgudev-1.0-dev, libproperties-cpp-dev, # for coverage reports lcov, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d3a021b..cdd2384 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ add_library( indicator.cpp rotation-lock.cpp usb-manager.cpp + usb-monitor.cpp usb-snap.cpp ) diff --git a/src/adbd-client.cpp b/src/adbd-client.cpp index 4f7d28f..937215e 100644 --- a/src/adbd-client.cpp +++ b/src/adbd-client.cpp @@ -45,6 +45,7 @@ public: { // tell the worker thread to stop whatever it's doing and exit. g_cancellable_cancel(m_cancellable); + m_pkresponse_cv.notify_one(); m_sleep_cv.notify_one(); m_worker_thread.join(); g_clear_object(&m_cancellable); diff --git a/src/main.cpp b/src/main.cpp index 7d6eb5f..27e6bcc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include // bindtextdomain() #include @@ -59,7 +60,8 @@ main(int /*argc*/, char** /*argv*/) // even though it doesn't have an indicator component yet static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adbd"}; static constexpr char const * PUBLIC_KEYS_FILENAME {"/data/misc/adb/adb_keys"}; - UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME}; + auto usb_monitor = std::make_shared(); + UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME, usb_monitor}; // let's go! g_main_loop_run(loop); diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 7f43520..840a04b 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -28,39 +28,57 @@ #include #include +#include + class UsbManager::Impl { public: explicit Impl( const std::string& socket_path, - const std::string& public_keys_filename + const std::string& public_keys_filename, + const std::shared_ptr& usb_monitor ): m_adbd_client{std::make_shared(socket_path)}, - m_public_keys_filename{public_keys_filename} + m_public_keys_filename{public_keys_filename}, + m_usb_monitor{usb_monitor} { - m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ - auto snap = new UsbSnap(req.fingerprint); - snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(req.public_key); - // delete_later - g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); - }); + m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { + m_snap.reset(); }); - } - ~Impl() - { + m_adbd_client->on_pk_request().connect( + [this](const AdbdClient::PKRequest& req){ + + m_snap.reset(new UsbSnap(req.fingerprint), + [this](UsbSnap* snap){ + m_snap_connections.clear(); + delete snap; + } + ); + + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this,req](AdbdClient::PKResponse response, bool remember_choice){ + g_message("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + req.respond(response); + g_message("%s", G_STRLOC); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->m_snap.reset(); return G_SOURCE_REMOVE;}, this); + } + )); + } + ); + } + ~Impl() =default; + private: void write_public_key(const std::string& public_key) { - g_debug("writing public key '%s' to '%s'", public_key.c_str(), m_public_keys_filename.c_str()); + g_message("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); // confirm the directory exists auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); @@ -78,12 +96,12 @@ private: S_IRUSR|S_IWUSR|S_IRGRP ); if (fd == -1) { - g_warning("Error opening ADB datafile '%s': %s", m_public_keys_filename.c_str(), g_strerror(errno)); + g_warning("Error opening ADB datafile: %s", g_strerror(errno)); return; } // write the new public key on its own line - const std::string buf {public_key + '\n'}; + std::string buf {public_key + '\n'}; if (write(fd, buf.c_str(), buf.size()) == -1) g_warning("Error writing ADB datafile: %d %s", errno, g_strerror(errno)); close(fd); @@ -91,6 +109,10 @@ private: std::shared_ptr m_adbd_client; const std::string m_public_keys_filename; + std::shared_ptr m_usb_monitor; + + std::shared_ptr m_snap; + std::set m_snap_connections; }; /*** @@ -99,9 +121,10 @@ private: UsbManager::UsbManager( const std::string& socket_path, - const std::string& public_keys_filename + const std::string& public_keys_filename, + const std::shared_ptr& usb_monitor ): - impl{new Impl{socket_path, public_keys_filename}} + impl{new Impl{socket_path, public_keys_filename, usb_monitor}} { } diff --git a/src/usb-manager.h b/src/usb-manager.h index ec405c0..960d634 100644 --- a/src/usb-manager.h +++ b/src/usb-manager.h @@ -19,6 +19,8 @@ #pragma once +#include + #include #include @@ -28,10 +30,17 @@ class UsbManager { public: - UsbManager(const std::string& socket_path, const std::string& public_key_filename); + + UsbManager( + const std::string& socket_path, + const std::string& public_key_filename, + const std::shared_ptr& + ); + ~UsbManager(); protected: + class Impl; std::unique_ptr impl; }; diff --git a/src/usb-monitor.cpp b/src/usb-monitor.cpp new file mode 100644 index 0000000..5fc5a6d --- /dev/null +++ b/src/usb-monitor.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include +#include + +class GUDevUsbMonitor::Impl +{ +public: + + Impl() + { + const char* subsystems[] = {"android_usb", nullptr}; + m_udev_client = g_udev_client_new(subsystems); + g_signal_connect(m_udev_client, "uevent", G_CALLBACK(on_android_usb_event), this); + } + + ~Impl() + { + g_signal_handlers_disconnect_by_data(m_udev_client, this); + g_clear_object(&m_udev_client); + } + + core::Signal& on_usb_disconnected() + { + return m_on_usb_disconnected; + } + +private: + + static void on_android_usb_event(GUdevClient*, gchar* action, GUdevDevice* device, gpointer gself) + { + if (!g_strcmp0(action, "change")) + if (!g_strcmp0(g_udev_device_get_property(device, "USB_STATE"), "DISCONNECTED")) + static_cast(gself)->m_on_usb_disconnected(g_udev_device_get_name(device)); + } + + core::Signal m_on_usb_disconnected; + + GUdevClient* m_udev_client = nullptr; +}; + +/*** +**** +***/ + +UsbMonitor::UsbMonitor() =default; + +UsbMonitor::~UsbMonitor() =default; + +GUDevUsbMonitor::GUDevUsbMonitor(): + impl{new Impl{}} +{ +} + +GUDevUsbMonitor::~GUDevUsbMonitor() =default; + +core::Signal& +GUDevUsbMonitor::on_usb_disconnected() +{ + return impl->on_usb_disconnected(); +} + diff --git a/src/usb-monitor.h b/src/usb-monitor.h new file mode 100644 index 0000000..d9be539 --- /dev/null +++ b/src/usb-monitor.h @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include + +#include +#include + +/** + * Simple interface that emits signals on USB device state changes + */ +class UsbMonitor +{ +public: + UsbMonitor(); + virtual ~UsbMonitor(); + virtual core::Signal& on_usb_disconnected() =0; +}; + +/** + * Simple GUDev wrapper that notifies on android_usb device state changes + */ +class GUDevUsbMonitor: public UsbMonitor +{ +public: + GUDevUsbMonitor(); + virtual ~GUDevUsbMonitor(); + core::Signal& on_usb_disconnected() override; + +protected: + class Impl; + std::unique_ptr impl; +}; + diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 41c78c6..349d80e 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -148,6 +148,7 @@ private: { GError* error {}; auto reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION(obus), res, &error); +g_message("%s got notify response %s", G_STRLOC, g_variant_print(reply, true)); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning("UsbSnap: Error calling Notify: %s", error->message); diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index 21fdc97..19c0401 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -17,10 +17,9 @@ * Charles Kerr */ -#define QT_NO_KEYWORDS - #include #include +#include #include #include @@ -64,6 +63,8 @@ protected: { super::SetUp(); + m_usb_monitor.reset(new MockUsbMonitor{}); + char tmpl[] = {"usb-manager-test-XXXXXX"}; m_tmpdir.reset(new std::string{g_mkdtemp(tmpl)}, file_deleter); g_message("using tmpdir '%s'", m_tmpdir->c_str()); @@ -83,6 +84,7 @@ protected: QtDBusTest::DBusTestRunner dbusTestRunner; QtDBusMock::DBusMock dbusMock; std::shared_ptr m_tmpdir; + std::shared_ptr m_usb_monitor; }; TEST_F(UsbManagerFixture, Allow) @@ -102,7 +104,7 @@ TEST_F(UsbManagerFixture, Allow) auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); // set up a UsbManager to process the request - auto usb_manager = std::make_shared(*socket_path, *public_keys_path); + auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor); // wait for the notification to show up, confirm it looks right wait_for_signals(notificationsSpy, 1); @@ -151,3 +153,39 @@ TEST_F(UsbManagerFixture, Allow) ASSERT_EQ(1, lines.size()); EXPECT_EQ(public_key, lines[0]); } + +TEST_F(UsbManagerFixture, Cancel) +{ + const std::shared_ptr socket_path {new std::string{*m_tmpdir+"/socket"}, file_deleter}; + const std::shared_ptr public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; + + // add a signal spy to listen to the notification daemon + QSignalSpy notificationsSpy( + ¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &)) + ); + + // start a mock AdbdServer ready to submit a request + const std::string public_key {"public_key"}; + auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); + + // set up a UsbManager to process the request + auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor); + + // wait for a notification to show up + wait_for_signals(notificationsSpy, 1); + EXPECT_EQ("Notify", notificationsSpy.at(0).at(0)); + notificationsSpy.clear(); + + // wait for UsbSnap to receive dbusmock's response to the Notify request. + // there's no event to key off of for this, so just wait for a moment + wait_msec(); + + // disconnect the USB before the user has a chance to allow/deny + m_usb_monitor->m_on_usb_disconnected("android0"); + + // confirm that we requested the notification to be pulled down + wait_for_signals(notificationsSpy, 1); + EXPECT_EQ("CloseNotification", notificationsSpy.at(0).at(0)); + notificationsSpy.clear(); +} diff --git a/tests/unit/usb-snap-test.cpp b/tests/unit/usb-snap-test.cpp index 663f9e6..40de94a 100644 --- a/tests/unit/usb-snap-test.cpp +++ b/tests/unit/usb-snap-test.cpp @@ -17,7 +17,6 @@ * Charles Kerr */ -#define QT_NO_KEYWORDS #include #include diff --git a/tests/utils/mock-usb-monitor.h b/tests/utils/mock-usb-monitor.h new file mode 100644 index 0000000..92b89db --- /dev/null +++ b/tests/utils/mock-usb-monitor.h @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include + +class MockUsbMonitor: public UsbMonitor +{ +public: + MockUsbMonitor() =default; + virtual ~MockUsbMonitor() =default; + core::Signal& on_usb_disconnected() override {return m_on_usb_disconnected;} + core::Signal m_on_usb_disconnected; +}; + diff --git a/tests/utils/qdbus-helpers.h b/tests/utils/qdbus-helpers.h deleted file mode 100644 index f873e23..0000000 --- a/tests/utils/qdbus-helpers.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#define QT_NO_KEYWORDS -#include -#include - -bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) -{ - if (variant.canConvert()) - { - QDBusArgument value(variant.value()); - if (value.currentType() == QDBusArgument::MapType) - { - value >> map; - return true; - } - } - - return false; -} - diff --git a/tests/utils/qt-fixture.h b/tests/utils/qt-fixture.h index 321d56e..0f5722b 100644 --- a/tests/utils/qt-fixture.h +++ b/tests/utils/qt-fixture.h @@ -22,12 +22,13 @@ #define QT_NO_KEYWORDS #include -#include #include #include #include +#include +#include #include class QtFixture: public GlibFixture @@ -54,5 +55,20 @@ protected: ASSERT_EQ(signalsExpected, signalSpy.size()); } + + bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) + { + if (variant.canConvert()) + { + QDBusArgument value(variant.value()); + if (value.currentType() == QDBusArgument::MapType) + { + value >> map; + return true; + } + } + + return false; + } }; -- cgit v1.2.3 From 1c4f005f0765f460b28808a624fbec7737324b1a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 21 Mar 2016 17:05:01 -0500 Subject: in UsbManager, reset AdbdClient on usb disconnect --- src/usb-manager.cpp | 44 ++++++++++++++++++++++++++------------------ src/usb-snap.cpp | 1 - 2 files changed, 26 insertions(+), 19 deletions(-) (limited to 'src/usb-manager.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 840a04b..f5957d9 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -39,29 +39,40 @@ public: const std::string& public_keys_filename, const std::shared_ptr& usb_monitor ): - m_adbd_client{std::make_shared(socket_path)}, + m_socket_path{socket_path}, m_public_keys_filename{public_keys_filename}, m_usb_monitor{usb_monitor} { m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { - m_snap.reset(); + restart(); }); + restart(); + } + + ~Impl() =default; + +private: + + void restart() + { + // clear out old state + m_snap_connections.clear(); + m_snap.reset(); + m_adbd_client.reset(); + + // add a new client + m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( - [this](const AdbdClient::PKRequest& req){ + [this](const AdbdClient::PKRequest& req) { - m_snap.reset(new UsbSnap(req.fingerprint), - [this](UsbSnap* snap){ - m_snap_connections.clear(); - delete snap; - } - ); + g_debug("%s got pk request", G_STRLOC); + m_snap = std::make_shared(req.fingerprint); m_snap_connections.insert((*m_snap).on_user_response().connect( [this,req](AdbdClient::PKResponse response, bool remember_choice){ - g_message("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); req.respond(response); - g_message("%s", G_STRLOC); if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) write_public_key(req.public_key); g_idle_add([](gpointer gself){static_cast(gself)->m_snap.reset(); return G_SOURCE_REMOVE;}, this); @@ -69,16 +80,11 @@ public: )); } ); - } - ~Impl() =default; - -private: - void write_public_key(const std::string& public_key) { - g_message("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); + g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); // confirm the directory exists auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); @@ -107,10 +113,12 @@ private: close(fd); } - std::shared_ptr m_adbd_client; + const std::string m_socket_path; const std::string m_public_keys_filename; + std::shared_ptr m_usb_monitor; + std::shared_ptr m_adbd_client; std::shared_ptr m_snap; std::set m_snap_connections; }; diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 349d80e..41c78c6 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -148,7 +148,6 @@ private: { GError* error {}; auto reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION(obus), res, &error); -g_message("%s got notify response %s", G_STRLOC, g_variant_print(reply, true)); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning("UsbSnap: Error calling Notify: %s", error->message); -- cgit v1.2.3 From a5f330f6b73101d7bbdeadc6a5f53b8da3349999 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 22 Mar 2016 15:39:36 -0500 Subject: don't show the snap decision until we're out of the greeter --- src/main.cpp | 2 +- src/usb-manager.cpp | 76 +++++++++++++++++++++++++++++++++------------- src/usb-manager.h | 4 ++- tests/utils/mock-greeter.h | 32 +++++++++++++++++++ 4 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 tests/utils/mock-greeter.h (limited to 'src/usb-manager.cpp') diff --git a/src/main.cpp b/src/main.cpp index 6c111f1..52cdd58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,7 +64,7 @@ main(int /*argc*/, char** /*argv*/) static constexpr char const * PUBLIC_KEYS_FILENAME {"/data/misc/adb/adb_keys"}; auto usb_monitor = std::make_shared(); auto greeter = std::make_shared(); - UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME, usb_monitor}; + UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME, usb_monitor, greeter}; // let's go! g_main_loop_run(loop); diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index f5957d9..0e59ca2 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -37,51 +37,83 @@ public: explicit Impl( const std::string& socket_path, const std::string& public_keys_filename, - const std::shared_ptr& usb_monitor + const std::shared_ptr& usb_monitor, + const std::shared_ptr& greeter ): m_socket_path{socket_path}, m_public_keys_filename{public_keys_filename}, - m_usb_monitor{usb_monitor} + m_usb_monitor{usb_monitor}, + m_greeter{greeter} { m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { restart(); }); + m_greeter->is_active().changed().connect([this](bool /*is_active*/) { + maybe_snap_now(); + }); + restart(); } - ~Impl() =default; + ~Impl() + { + clear(); + } private: - void restart() + void clear() { // clear out old state m_snap_connections.clear(); m_snap.reset(); + m_req = AdbdClient::PKRequest{}; m_adbd_client.reset(); + } - // add a new client + void restart() + { + clear(); + + // set a new client m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( [this](const AdbdClient::PKRequest& req) { - g_debug("%s got pk request", G_STRLOC); - - m_snap = std::make_shared(req.fingerprint); - m_snap_connections.insert((*m_snap).on_user_response().connect( - [this,req](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->m_snap.reset(); return G_SOURCE_REMOVE;}, this); - } - )); + m_req = req; + maybe_snap_now(); } ); } + bool ready_to_snap() + { + return !m_greeter->is_active().get() && !m_req.public_key.empty(); + } + + void maybe_snap_now() + { + if (ready_to_snap()) + snap_now(); + } + + void snap_now() + { + g_return_if_fail(ready_to_snap()); + + m_snap = std::make_shared(m_req.fingerprint); + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + m_req.respond(response); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(m_req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + } + )); + } + void write_public_key(const std::string& public_key) { g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); @@ -115,10 +147,11 @@ private: const std::string m_socket_path; const std::string m_public_keys_filename; - - std::shared_ptr m_usb_monitor; + const std::shared_ptr m_usb_monitor; + const std::shared_ptr m_greeter; std::shared_ptr m_adbd_client; + AdbdClient::PKRequest m_req; std::shared_ptr m_snap; std::set m_snap_connections; }; @@ -130,9 +163,10 @@ private: UsbManager::UsbManager( const std::string& socket_path, const std::string& public_keys_filename, - const std::shared_ptr& usb_monitor + const std::shared_ptr& usb_monitor, + const std::shared_ptr& greeter ): - impl{new Impl{socket_path, public_keys_filename, usb_monitor}} + impl{new Impl{socket_path, public_keys_filename, usb_monitor, greeter}} { } diff --git a/src/usb-manager.h b/src/usb-manager.h index 960d634..b93992f 100644 --- a/src/usb-manager.h +++ b/src/usb-manager.h @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -34,7 +35,8 @@ public: UsbManager( const std::string& socket_path, const std::string& public_key_filename, - const std::shared_ptr& + const std::shared_ptr&, + const std::shared_ptr& ); ~UsbManager(); diff --git a/tests/utils/mock-greeter.h b/tests/utils/mock-greeter.h new file mode 100644 index 0000000..5ac85a0 --- /dev/null +++ b/tests/utils/mock-greeter.h @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include + +class MockGreeter: public Greeter +{ +public: + MockGreeter() =default; + virtual ~MockGreeter() =default; + core::Property& is_active() override {return m_is_active;} + core::Property m_is_active {false}; +}; + -- cgit v1.2.3 From 4f8a17f23a0bba7da7654c147ca377e271abe0db Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 22 Mar 2016 16:01:47 -0500 Subject: add tests for not showing snap decisions in greeter mode --- src/usb-manager.cpp | 48 ++++++++++++---------------------- tests/integration/usb-manager-test.cpp | 34 +++++++++++++++++++++--- tests/utils/adbd-server.h | 8 +++--- 3 files changed, 51 insertions(+), 39 deletions(-) (limited to 'src/usb-manager.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 0e59ca2..4fdfdc1 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -50,7 +50,7 @@ public: }); m_greeter->is_active().changed().connect([this](bool /*is_active*/) { - maybe_snap_now(); + restart(); }); restart(); @@ -68,7 +68,6 @@ private: // clear out old state m_snap_connections.clear(); m_snap.reset(); - m_req = AdbdClient::PKRequest{}; m_adbd_client.reset(); } @@ -76,44 +75,30 @@ private: { clear(); + // don't prompt in the greeter! + if (m_greeter->is_active().get()) + return; + // set a new client +g_message("creating a new adbd client"); m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( [this](const AdbdClient::PKRequest& req) { g_debug("%s got pk request", G_STRLOC); - m_req = req; - maybe_snap_now(); + m_snap = std::make_shared(req.fingerprint); + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this,req](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + req.respond(response); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + } + )); } ); } - bool ready_to_snap() - { - return !m_greeter->is_active().get() && !m_req.public_key.empty(); - } - - void maybe_snap_now() - { - if (ready_to_snap()) - snap_now(); - } - - void snap_now() - { - g_return_if_fail(ready_to_snap()); - - m_snap = std::make_shared(m_req.fingerprint); - m_snap_connections.insert((*m_snap).on_user_response().connect( - [this](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - m_req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(m_req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); - } - )); - } - void write_public_key(const std::string& public_key) { g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); @@ -151,7 +136,6 @@ private: const std::shared_ptr m_greeter; std::shared_ptr m_adbd_client; - AdbdClient::PKRequest m_req; std::shared_ptr m_snap; std::set m_snap_connections; }; diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index 3ce79d0..03c80c7 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -87,7 +87,7 @@ protected: QtDBusMock::DBusMock dbusMock; std::shared_ptr m_tmpdir; std::shared_ptr m_usb_monitor; - std::shared_ptr m_greeter; + std::shared_ptr m_greeter; }; TEST_F(UsbManagerFixture, Allow) @@ -157,7 +157,7 @@ TEST_F(UsbManagerFixture, Allow) EXPECT_EQ(public_key, lines[0]); } -TEST_F(UsbManagerFixture, AndroidInterruptus) +TEST_F(UsbManagerFixture, USBDisconnectedDuringPrompt) { const std::shared_ptr socket_path {new std::string{*m_tmpdir+"/socket"}, file_deleter}; const std::shared_ptr public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; @@ -171,7 +171,6 @@ TEST_F(UsbManagerFixture, AndroidInterruptus) for (int i=0; i<3; i++) { -g_message("i %d", i); // add a signal spy to listen to the notification daemon QSignalSpy notificationsSpy( ¬ificationsMockInterface(), @@ -196,3 +195,32 @@ g_message("i %d", i); notificationsSpy.clear(); } } + +TEST_F(UsbManagerFixture, Greeter) +{ + const std::shared_ptr socket_path {new std::string{*m_tmpdir+"/socket"}, file_deleter}; + const std::shared_ptr public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; + + // start a mock AdbdServer ready to submit a request + const std::string public_key {"public_key"}; + auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); + + // set up a UsbManager to process the request + m_greeter->m_is_active.set(true); + auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor, m_greeter); + + // add a signal spy to listen to the notification daemon + QSignalSpy notificationsSpy( + ¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &)) + ); + + // the greeter is active, so the notification should not appear + EXPECT_FALSE(notificationsSpy.wait(2000)); + + // disable the greeter, the notification should appear + m_greeter->m_is_active.set(false); + wait_for_signals(notificationsSpy, 1); + EXPECT_EQ("Notify", notificationsSpy.at(0).at(0)); + notificationsSpy.clear(); +} diff --git a/tests/utils/adbd-server.h b/tests/utils/adbd-server.h index 968c1f0..5e66379 100644 --- a/tests/utils/adbd-server.h +++ b/tests/utils/adbd-server.h @@ -73,7 +73,7 @@ private: auto client_socket = g_socket_accept(server_socket, m_cancellable, &error); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("GAdbdServer: Error accepting socket connection: %s", error->message); + g_message("GAdbdServer: Error accepting socket connection: %s", error->message); g_clear_error(&error); break; } @@ -90,7 +90,7 @@ private: &error); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("GAdbdServer: Error sending request: %s", error->message); + g_message("GAdbdServer: Error sending request: %s", error->message); g_clear_error(&error); g_clear_object(&client_socket); break; @@ -106,10 +106,10 @@ private: &error); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("GAdbdServer: Error reading response: %s", error->message); + g_message("GAdbdServer: Error reading response: %s", error->message); g_clear_error(&error); g_clear_object(&client_socket); - break; + continue; } const std::string response(buf, std::string::size_type(n_bytes)); g_message("server got response: %s", response.c_str()); -- cgit v1.2.3 From ccc831d425006a803ca64c5525d38fef8912aac5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Mar 2016 14:02:48 -0500 Subject: keep the adbd socket open even when the lockscreen is closed. hold the pkrequest state in USBManager until the screen's unlocked. --- src/usb-manager.cpp | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) (limited to 'src/usb-manager.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 4fdfdc1..656b6a0 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -50,7 +50,7 @@ public: }); m_greeter->is_active().changed().connect([this](bool /*is_active*/) { - restart(); + maybe_snap(); }); restart(); @@ -68,6 +68,7 @@ private: // clear out old state m_snap_connections.clear(); m_snap.reset(); + m_req = decltype(m_req){}; m_adbd_client.reset(); } @@ -75,30 +76,38 @@ private: { clear(); - // don't prompt in the greeter! - if (m_greeter->is_active().get()) - return; - // set a new client -g_message("creating a new adbd client"); m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( [this](const AdbdClient::PKRequest& req) { - g_debug("%s got pk request", G_STRLOC); - m_snap = std::make_shared(req.fingerprint); - m_snap_connections.insert((*m_snap).on_user_response().connect( - [this,req](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); - } - )); + g_debug("%s got pk request: %s", G_STRLOC, req.fingerprint.c_str()); + m_req = req; + maybe_snap(); } ); } + void maybe_snap() + { + // don't prompt in the greeter! + if (!m_req.public_key.empty() && !m_greeter->is_active().get()) + snap(); + } + + void snap() + { + m_snap = std::make_shared(m_req.fingerprint); + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + m_req.respond(response); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(m_req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + } + )); + } + void write_public_key(const std::string& public_key) { g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); @@ -136,6 +145,7 @@ g_message("creating a new adbd client"); const std::shared_ptr m_greeter; std::shared_ptr m_adbd_client; + AdbdClient::PKRequest m_req; std::shared_ptr m_snap; std::set m_snap_connections; }; -- cgit v1.2.3 From 8f396a525d1353d724b6a96b8a777be2dde35984 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Mar 2016 14:12:05 -0500 Subject: fix missing field initialization compiler warning --- src/usb-manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/usb-manager.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 656b6a0..f67f0e2 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -68,7 +68,7 @@ private: // clear out old state m_snap_connections.clear(); m_snap.reset(); - m_req = decltype(m_req){}; + m_req = decltype(m_req)(); m_adbd_client.reset(); } -- cgit v1.2.3 From 9f03876ba4aef09f5b93905f90df9a7b9d1073e4 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Mar 2016 14:44:23 -0500 Subject: fix UsbManager dtor issue found by valgrind --- src/usb-manager.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/usb-manager.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index f67f0e2..4d750c0 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -58,6 +58,9 @@ public: ~Impl() { + if (m_restart_idle_tag) + g_source_remove(m_restart_idle_tag); + clear(); } @@ -103,7 +106,12 @@ private: m_req.respond(response); if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) write_public_key(m_req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + m_restart_idle_tag = g_idle_add([](gpointer gself){ + auto self = static_cast(gself); + self->m_restart_idle_tag = 0; + self->restart(); + return G_SOURCE_REMOVE; + }, this); } )); } @@ -143,6 +151,8 @@ private: const std::string m_public_keys_filename; const std::shared_ptr m_usb_monitor; const std::shared_ptr m_greeter; + + unsigned int m_restart_idle_tag {}; std::shared_ptr m_adbd_client; AdbdClient::PKRequest m_req; -- cgit v1.2.3