mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-08 19:13:25 -08:00
[Installer] Ask a hidden instance to close, then offer to end it once (#7683)
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 26 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 26 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions
* [Installer] Request quit for hidden Cockatrice instances and record holders in abort telemetry * [Installer] Fix compiler warnings in holder probe and installer quit handler * [VisualDeckStorage] Order the includes the way clang-format wants them * [Installer] Ask a hidden instance to close, then offer to end it once The previous attempt had the client answer a registered window message, which cannot work for the update it was reported on: the instance being replaced is a client from before that message exists, so it never answers, and the user is left with "Cockatrice is still running" exactly as reported. Every step that can free the files has to be the installer's, so the client side is reverted. The probe now posts WM_CLOSE to the instance's own window whether that window is on screen or only in the notification area: the request does not need a visible window, an instance in the tray is the one this update has no other way to reach, and the confirmation Cockatrice answers with is a window Qt shows itself, so it is painted - unlike one restored from outside. A visible window is brought forward first, and Qt's bookkeeping windows stay excluded, because a close to the notification-area one terminates the instance without its confirmation. A question of the instance's own no longer suppresses the close. Withholding it protected nobody: the installer asked the user to close a program it had never asked, and a current client refuses the close while its confirmation is pending anyway, leaving the question where it is. The launcher mode keeps the visible-only rule, because a launcher without a window has already answered its own close and the wait ends it after a grace instead of asking a user who is not there. The guard asked the same question until the user gave up: after the automatic close failed it offered to end the programs, then re-ran the probe and showed the same dialog word for word when the answer was No, which is how an abort was reported three times over. It now asks once - Yes ends the Cockatrice, Oracle and Servatrice programs the payload installs and says what that costs, No cancels - and what survives an end is named in the abort instead of being put to the user as the same question again. The uninstaller's guard and the recovery path after a failed purge follow the same shape. Kept: the abort telemetry that records the holders, the close result and the end result as event data. --------- Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com> Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
parent
9e50c5ad6e
commit
ded83aaab5
7 changed files with 223 additions and 165 deletions
|
|
@ -10,15 +10,15 @@
|
|||
* @brief What asking the holders to close did, in the form the installer logs.
|
||||
*
|
||||
* @c report is one line naming every holder, including the ones this deliberately
|
||||
* leaves alone, because the installer repeats it in its log and in the second prompt.
|
||||
* @c withoutWindow counts the holders that had no visible window a user could answer: they
|
||||
* were named and left alone, and the launcher mode reads that count as "nothing to ask"
|
||||
* rather than as a window the user still has to answer.
|
||||
* leaves alone, because the installer repeats it in its log.
|
||||
* @c withoutWindow counts the holders that had no window of their own to ask: they were
|
||||
* named and left alone, and the launcher mode reads that count as "nothing to ask" rather
|
||||
* than as a window the user still has to answer.
|
||||
*/
|
||||
struct CloseHoldersResult
|
||||
{
|
||||
unsigned int askedToClose = 0; ///< holders a WM_CLOSE was posted to
|
||||
unsigned int withoutWindow = 0; ///< holders with no visible window a user could answer
|
||||
unsigned int withoutWindow = 0; ///< holders with no window of their own to ask
|
||||
std::wstring report; ///< one line, narrowed to ASCII when written
|
||||
};
|
||||
|
||||
|
|
@ -42,27 +42,34 @@ bool isCockatriceImage(const std::wstring &imageName);
|
|||
* asked to close. Oracle and Servatrice are left to the user - Oracle writes the card
|
||||
* database in place - and so is every service.
|
||||
*
|
||||
* One thing happens per instance: its main window is brought to the foreground, because
|
||||
* Cockatrice may answer the close with a confirmation of its own that would otherwise open
|
||||
* behind the installer's prompt. Then WM_CLOSE is posted to the main window, the same
|
||||
* request as clicking its close button - unless the instance is asking a question of its
|
||||
* own, which disables that window: posting the close then only hides the question, so it is
|
||||
* brought forward and left to the user. An instance with no window a user could answer -
|
||||
* one hidden in the notification area, say - is named and left to the user as well; showing
|
||||
* its windows from here does not help, because the application would still believe they are
|
||||
* hidden and never paint them. Stopping the process is never attempted.
|
||||
* One thing happens per instance: its own window is asked to close with WM_CLOSE, the same
|
||||
* request as clicking that window's close button - whether it is on screen or only in the
|
||||
* notification area, since the request does not need the window to be visible and the
|
||||
* confirmation Cockatrice answers it with is a window Qt shows itself, painted, unlike one
|
||||
* restored from outside. A window that is on screen is brought forward first, because that
|
||||
* confirmation would otherwise open behind the installer's prompt; nothing is shown from
|
||||
* here. Qt's own bookkeeping windows are never the target - posting a close to the
|
||||
* notification-area one terminates the instance without its confirmation - so a process
|
||||
* without a window of its own is named and left to the guard, which offers to end it.
|
||||
* Stopping the process is never attempted here.
|
||||
*
|
||||
* Once the requests are out, this waits up to @c waitMilliseconds for the processes to
|
||||
* exit, so the caller can measure the purge immediately afterwards instead of sleeping
|
||||
* for a fixed time or re-asking a question this call already answered. A process that is
|
||||
* still running is described further: whether its window is gone, still open, hidden
|
||||
* again, and whether it answers at all, so the log can tell an instance that refused the
|
||||
* close from one that never received it.
|
||||
* still running is described further: whether its window is gone, still open, still
|
||||
* hidden or hidden again, and whether it answers at all, so the log can tell an instance
|
||||
* that refused the close from one that never received it.
|
||||
*
|
||||
* @param holders the Restart Manager answer, one entry per application or service
|
||||
* @param waitMilliseconds how long to wait for the asked instances to exit, 0 to not wait
|
||||
* @param askHiddenWindows whether a window that is not on screen is asked to close too.
|
||||
* The guard wants that: an instance in the notification area is the one this update
|
||||
* has no other way to reach. The launcher mode does not - a launcher without a
|
||||
* visible window has already answered its own close and is stuck in shutdown, and
|
||||
* the installer ends it instead of putting a question to a user who is not there.
|
||||
*/
|
||||
CloseHoldersResult closeCockatriceHolders(const std::vector<Holder> &holders, unsigned long waitMilliseconds);
|
||||
CloseHoldersResult
|
||||
closeCockatriceHolders(const std::vector<Holder> &holders, unsigned long waitMilliseconds, bool askHiddenWindows);
|
||||
|
||||
/**
|
||||
* @brief What ending the holders did, in the form the installer logs.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue