Category: Uncategorized

  • GSoC Final Report

    Google Summer of Code 2026: Native App Uninstallation in GNOME Shell

    This summer, I spent my Google Summer of Code working on something I’ve wanted to see for a while, making it possible to uninstall apps right from the GNOME Shell app grid. Before this, if you wanted to remove an app, you had to open up GNOME Software, hunt it down, and delete it from there. My goal was to completely remove that friction. By connecting GNOME Shell and GNOME Software behind the scenes using D-Bus, I made it so users can securely delete apps with just a couple of clicks right from the desktop


    GitLab Links to Code

    GNOME Shell: App Grid Uninstallation Frontend

    This Merge Request covers all the frontend work I did in GNOME Shell. The brain behind it all is a new class called AppStoreIntegrationManager. Think of it as both a state tracker and our bridge to GNOME Software. When it boots up, it connects to GNOME Software asynchronously over D-Bus using the org.gnome.Shell.AppStoreIntegration interface.

    To keep the app grid feeling snappy, I didn’t want to query the app store every single time a user right-clicks an icon. Instead, the manager grabs the dictionary of uninstallable apps and caches it in memory. To make sure this cache is always accurate, it listens for installed-changed signals from Shell.AppSystem and quietly updates itself in the background.

    Because the data is cached, the UI just has to react to it. When you open the context menu, it checks if the app is in our cache; if it is, the “Uninstall” button appears. This is a great way to prevent users from accidentally trying to delete core system apps. Once a user clicks uninstall, the frontend checks if the app supports purging user data. If it does, a confirmation dialog pops up with a checkbox to wipe those files. After confirming, the app goes into a tracking Set (_uninstallingApps). This immediately tells GNOME Shell to remove the app icon from the grid right away, giving the user instant visual feedback that the app is gone. Finally, if the background job finishes successfully, it happens silently without spamming the user with notifications. However, if the uninstallation fails for any reason, a system notification pops up to let the user know what went wrong.

    GNOME Software: App Store Integration Backend

    This Merge Request focuses on the backend GNOME Software. It’s essentially the engine that listens to GNOME Shell and handles the actual uninstallation and data purging. To make this work, I built a custom GObject called GsAppStoreIntegrationBackend. This object exposes the necessary D-Bus methods and acts as a safe router, directing GNOME Shell’s queries straight into the GsPluginLoader.

    When the Shell asks for the list of uninstallable apps via the GetUninstallableApps method, we can’t afford to make it wait while we search the entire software catalog. Instead, the backend fires off a GsAppQuery using gs_plugin_job_list_apps_new to quickly grab only the installed apps. I also built in a strict safety net: if an application is tagged with the GS_APP_QUIRK_COMPULSORY quirk, we automatically strip it out of the response. That way, GNOME Shell never even gets the chance to offer a “Delete” button for critical OS components like Settings.

    I also spent a lot of time on secure data deletion, which is super important for sandboxed apps like Flatpaks. To pull this off, I extended the core plugin architecture by introducing a new flag, GS_PLUGIN_UNINSTALL_APPS_FLAGS_PURGE_DATA, to the GsPluginUninstallAppsFlags enumeration. Now, if a user checks that ‘wipe data’ box on the desktop, the backend attaches this flag to the uninstall job. I modified the Flatpak plugin (gs-plugin-flatpak.c) to intercept it. Once the standard uninstall finishes successfully, the plugin spots the flag and calls gs_utils_rmtree() to safely and recursively scrub the isolated app data right out of ~/.var/app/<app-id>.

    GUADEC 2026 Presentation

    Honestly, one of the absolute highlights of my summer wasn’t even the code, it was getting to share this project with the wider GNOME community at GUADEC 2026! I had a blast giving a talk about how this feature actually works under the hood. I walked through the technical hurdles of bridging GNOME Shell with GNOME Software.

    You can check out my presentation here


    What’s Next?

    This project might be wrapping up, but my time with GNOME is just getting started. My immediate goal is to finish up the its and bits and get it merged. Once that’s done, I’m already looking at my next feature to add, implementing drag-and-drop uninstallation into the app grid

    A huge thank you goes out to my mentor, Adrian. His patience and guidance meant everything to me this summer. He didn’t just review my code; he took the time to help me really understand the bigger architectural picture. Because of him, I’ve grown so much as a developer. I loved how he would take the time to explain the deep history of Linux architecture to me, like how default applications and URL schemes eventually paved the way for XDG Intents. Combined with all the practical debugging techniques he showed me, he really helped me level up this summer.

    It’s been an amazing ride, and I’m so excited to continue my journey with GNOME and the open source world!

  • Bringing App Uninstallation to the GNOME Shell App Grid

    Hey y’all! I’m Jagath Ramayanapu (Shyam) from India, and I’m a GNOME GSoC intern this year. This summer, I’m working on bringing app uninstallation directly to the GNOME Shell App Grid.

    Previously, to remove an app in GNOME, you had to open GNOME Software, find the app, and click Uninstall. With this feature, users will soon be able to uninstall apps directly from the App Grid’s context menu.

    This is the first of a two-part blog on how we are building this feature. In this post, we’ll cover the changes in GNOME Shell’s JavaScript that make it possible.

     

    The Problem: Talking to the App Store

    GNOME Shell is great at drawing your desktop, but it actually has no idea how to delete an app or clean up user data. To do that, it needs to ask a App Store like GNOME Software to do the heavy lifting.

    To solve this, we created a d-bus interface called AppStoreIntegration. You can think of it as a dedicated middleman whose only job is to talk to GNOME Software in the background.

    We designed this helper with a few key goals in mind:

    At first, I planned to have GNOME Software own this interface. However, that would have tightly coupled the feature to GNOME Software. Based on feedback from my mentor, Adrian Vovk, I moved the ownership of AppStoreIntegration into GNOME Shell instead.

    This design makes the interface app store agnostic. Any app store can implement the interface, allowing GNOME Shell to work with different app stores without depending on a specific one.

    This interface has two methods :

    1. GetUninstallableApps :
      • What it does: The Shell calls this method to ask GNOME Software, “Give me a list of every installed app that the user is actually allowed to uninstall.”
      • What it returns: It returns a dictionary that maps each app’s desktop ID to a set of metadata properties (for example, a boolean flag telling us if the app supports deleting personal data)

    2. UninstallApp :

      • What it does: When you click “Uninstall”, the Shell sends this command to GNOME Software.
      • What it accepts: It takes a dictionary containing the app’s id and a boolean purge-data flag (which tells GNOME Software whether it should wipe the user’s saved data along with the app).

    Building the Integration Manager

    Now that we had our D-Bus contract, we built a helper module in GNOME Shell called js/ui/appStoreIntegration.js Inside this file, we built a class called AppStoreIntegrationManager whose sole purpose is to call those two D-Bus methods.

    We designed this manager with a few key goals:

    • Keep the Desktop Fast: When the manager connects to the D-Bus proxy, it does it asynchronously. This means if GNOME Software takes a second to wake up, your desktop won’t freeze.
    • Cache the Data: We don’t want to call GetUninstallableApps every single time you right-click an icon. Instead, the manager listens for a signal called installed-changed from the system. When it hears this signal, it quietly fetches the list of apps and caches it in memory.
    • Track the State: The manager keeps a list (set) of apps that are currently being uninstalled. This gives our UI a simple way to know exactly what is going on at any given moment.

    Updating the App Menu

    Once we had the cached data, we needed to update the UI in js/ui/appMenu.js.

    We added a new “Uninstall” button to the right-click menu, but we had to be careful. We don’t want to show an “Uninstall” button for apps you aren’t allowed to remove (like core system apps).

    To fix this, we tied the menu directly to our new manager using reactive signals. Every time you open the menu, a function called _updateUninstallItem runs. It asks the manager: appStoreIntegrationManager.canUninstall(appId). If the answer is false, the button completely hides itself.

    Handling the User Interaction

    Uninstalling an app isn’t always as simple as deleting a folder. Modern software, like Flatpaks, often leaves behind saved files and personal configurations. We wanted to give users the option to clean up this data, but only if the app store actually supports it.

    When you click Uninstall in the right-click menu, the UI triggers a smooth, step-by-step interactive flow:

    • Checking for User Data: First, the code checks the metadata we got from D-Bus earlier to see if the app store supports wiping personal data for this specific app.
    • The Confirmation Dialog: We pop up a small confirmation window. If the app supports it, this window includes a checkbox asking if you want to clean up your personal files too.
    • Waiting in the Background: The desktop interface pauses the uninstallation logic and waits patiently in the background for you to make a decision, ensuring your system remains completely responsive.
    • Executing the Uninstall: Once you confirm your choice, the UI fires off the D-Bus command to GNOME Software. It immediately adds the app to a tracking list to prevent you from accidentally clicking the uninstall button multiple times.
    • Safe Error Handling: If GNOME Software runs into an unexpected error and fails to uninstall the app, the interface safely catches the problem. It removes the app from the busy tracker and displays a standard system notification to let you know what happened, keeping your desktop totally stable.

    Thanks

    Building this feature was a fantastic learning experience in bridging different parts of the GNOME ecosystem. A huge thanks to Adrian for mentoring me throughout this project and helping me navigate the architecture.

    If you’d like to check out the changes, here’s my MR.