From 5e3a231f281cf4ff8897c623686fd28b22db5355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 15 Apr 2022 23:28:08 +0000 Subject: [PATCH] Bug 1762708 - Use async dbus for revealing files in nsGIOService. r=stransky This at least doesn't block the UI, even though the file could take a while to show up. Depends on D143606 Differential Revision: https://phabricator.services.mozilla.com/D143607 --- toolkit/system/gnome/nsGIOService.cpp | 108 +++++++++++++++++--------- xpcom/io/nsLocalFileUnix.cpp | 25 +----- xpcom/system/nsIGIOService.idl | 11 ++- 3 files changed, 80 insertions(+), 64 deletions(-) diff --git a/toolkit/system/gnome/nsGIOService.cpp b/toolkit/system/gnome/nsGIOService.cpp index 1358ea163310d..1ae749cdc1147 100644 --- a/toolkit/system/gnome/nsGIOService.cpp +++ b/toolkit/system/gnome/nsGIOService.cpp @@ -6,6 +6,7 @@ #include "nsGIOService.h" #include "nsString.h" #include "nsIURI.h" +#include "nsIFile.h" #include "nsTArray.h" #include "nsStringEnumerator.h" #include "nsIMIMEInfo.h" @@ -22,8 +23,7 @@ #include #include #ifdef MOZ_ENABLE_DBUS -# include -# include +# include "mozilla/widget/AsyncDBus.h" #endif using namespace mozilla; @@ -521,11 +521,9 @@ nsGIOService::GetDescriptionForMimeType(const nsACString& aMimeType, return NS_OK; } -NS_IMETHODIMP -nsGIOService::ShowURI(nsIURI* aURI) { +nsresult nsGIOService::ShowURI(nsIURI* aURI) { nsAutoCString spec; - nsresult rv = aURI->GetSpec(spec); - NS_ENSURE_SUCCESS(rv, rv); + MOZ_TRY(aURI->GetSpec(spec)); GUniquePtr error; if (!g_app_info_launch_default_for_uri(spec.get(), nullptr, getter_Transfers(error))) { @@ -536,10 +534,9 @@ nsGIOService::ShowURI(nsIURI* aURI) { return NS_OK; } -NS_IMETHODIMP -nsGIOService::ShowURIForInput(const nsACString& aUri) { +static nsresult LaunchPath(const nsACString& aPath) { RefPtr file = dont_AddRef( - g_file_new_for_commandline_arg(PromiseFlatCString(aUri).get())); + g_file_new_for_commandline_arg(PromiseFlatCString(aPath).get())); GUniquePtr spec(g_file_get_uri(file)); GUniquePtr error; g_app_info_launch_default_for_uri(spec.get(), nullptr, @@ -551,27 +548,35 @@ nsGIOService::ShowURIForInput(const nsACString& aUri) { return NS_OK; } -NS_IMETHODIMP -nsGIOService::OrgFreedesktopFileManager1ShowItems(const nsACString& aPath) { -#ifndef MOZ_ENABLE_DBUS - return NS_ERROR_FAILURE; -#else - GUniquePtr error; - RefPtr proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( - G_BUS_TYPE_SESSION, - GDBusProxyFlags(G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES), - nullptr, "org.freedesktop.FileManager1", "/org/freedesktop/FileManager1", - "org.freedesktop.FileManager1", nullptr, getter_Transfers(error))); - if (!proxy) { - g_printerr("Failed to create DBUS proxy for FileManager1: %s\n", - error->message); +nsresult nsGIOService::LaunchFile(const nsACString& aPath) { + return LaunchPath(aPath); +} + +static nsresult RevealDirectory(nsIFile* aFile, bool aForce) { + nsAutoCString path; + if (bool isDir; NS_SUCCEEDED(aFile->IsDirectory(&isDir)) && isDir) { + MOZ_TRY(aFile->GetNativePath(path)); + return LaunchPath(path); + } + + if (!aForce) { return NS_ERROR_FAILURE; } - GUniquePtr uri( - g_filename_to_uri(PromiseFlatCString(aPath).get(), nullptr, nullptr)); + nsCOMPtr parentDir; + MOZ_TRY(aFile->GetParent(getter_AddRefs(parentDir))); + MOZ_TRY(parentDir->GetNativePath(path)); + return LaunchPath(path); +} + +#ifdef MOZ_ENABLE_DBUS +static nsresult RevealFileViaDBusWithProxy(GDBusProxy* aProxy, nsIFile* aFile) { + nsAutoCString path; + MOZ_TRY(aFile->GetNativePath(path)); + + GUniquePtr uri(g_filename_to_uri(path.get(), nullptr, nullptr)); if (!uri) { + RevealDirectory(aFile, /* aForce = */ true); return NS_ERROR_FAILURE; } @@ -581,19 +586,52 @@ nsGIOService::OrgFreedesktopFileManager1ShowItems(const nsACString& aPath) { const int32_t timeout = StaticPrefs::widget_gtk_file_manager_show_items_timeout_ms(); - ; const char* startupId = ""; - RefPtr result = dont_AddRef(g_dbus_proxy_call_sync( - proxy, "ShowItems", g_variant_new("(ass)", &builder, startupId), - G_DBUS_CALL_FLAGS_NONE, timeout, nullptr, getter_Transfers(error))); - + widget::DBusProxyCall(aProxy, "ShowItems", + g_variant_new("(ass)", &builder, startupId), + G_DBUS_CALL_FLAGS_NONE, timeout) + ->Then( + GetCurrentSerialEventTarget(), __func__, + [](RefPtr&& aResult) { + // Do nothing, file is shown, we're done. + }, + [file = RefPtr{aFile}](GUniquePtr&& aError) { + g_printerr("Failed to query file manager: %s\n", aError->message); + RevealDirectory(file, /* aForce = */ true); + }); g_variant_builder_clear(&builder); - if (!result) { - g_printerr("Failed to query file manager: %s\n", error->message); - return NS_ERROR_FAILURE; - } + return NS_OK; +} + +static void RevealFileViaDBus(nsIFile* aFile) { + widget::CreateDBusProxyForBus( + G_BUS_TYPE_SESSION, + GDBusProxyFlags(G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES), + /* aInterfaceInfo = */ nullptr, "org.freedesktop.FileManager1", + "/org/freedesktop/FileManager1", "org.freedesktop.FileManager1") + ->Then( + GetCurrentSerialEventTarget(), __func__, + [file = RefPtr{aFile}](RefPtr&& aProxy) { + RevealFileViaDBusWithProxy(aProxy.get(), file); + }, + [file = RefPtr{aFile}](GUniquePtr&& aError) { + g_printerr("Failed to create DBUS proxy for FileManager1: %s\n", + aError->message); + RevealDirectory(file, /* aForce = */ true); + }); +} +#endif +nsresult nsGIOService::RevealFile(nsIFile* aFile) { +#ifdef MOZ_ENABLE_DBUS + if (NS_SUCCEEDED(RevealDirectory(aFile, /* aForce = */ false))) { + return NS_OK; + } + RevealFileViaDBus(aFile); return NS_OK; +#else + return RevealDirectory(aFile, /* aForce = */ true); #endif } diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp index 1558f0afb6cc3..f3f98008ed74a 100644 --- a/xpcom/io/nsLocalFileUnix.cpp +++ b/xpcom/io/nsLocalFileUnix.cpp @@ -2080,28 +2080,7 @@ nsLocalFile::Reveal() { if (!giovfs) { return NS_ERROR_FAILURE; } - - bool isDirectory; - if (NS_FAILED(IsDirectory(&isDirectory))) { - return NS_ERROR_FAILURE; - } - - if (isDirectory) { - return giovfs->ShowURIForInput(mPath); - } - if (NS_SUCCEEDED(giovfs->OrgFreedesktopFileManager1ShowItems(mPath))) { - return NS_OK; - } - nsCOMPtr parentDir; - nsAutoCString dirPath; - if (NS_FAILED(GetParent(getter_AddRefs(parentDir)))) { - return NS_ERROR_FAILURE; - } - if (NS_FAILED(parentDir->GetNativePath(dirPath))) { - return NS_ERROR_FAILURE; - } - - return giovfs->ShowURIForInput(dirPath); + return giovfs->RevealFile(this); #elif defined(MOZ_WIDGET_COCOA) CFURLRef url; if (NS_SUCCEEDED(GetCFURL(&url))) { @@ -2127,7 +2106,7 @@ nsLocalFile::Launch() { return NS_ERROR_FAILURE; } - return giovfs->ShowURIForInput(mPath); + return giovfs->LaunchFile(mPath); #elif defined(MOZ_WIDGET_ANDROID) // Not supported on GeckoView return NS_ERROR_NOT_IMPLEMENTED; diff --git a/xpcom/system/nsIGIOService.idl b/xpcom/system/nsIGIOService.idl index ebb1c8f0d89d8..99e6a02a32c77 100644 --- a/xpcom/system/nsIGIOService.idl +++ b/xpcom/system/nsIGIOService.idl @@ -8,6 +8,7 @@ interface nsIUTF8StringEnumerator; interface nsIURI; +interface nsIFile; interface nsIMutableArray; /* nsIGIOMimeApp holds information about an application that is looked up @@ -44,7 +45,7 @@ interface nsIGIOMimeApp : nsIHandlerApp */ // prev id dea20bf0-4e4d-48c5-b932-dc3e116dc64b -[scriptable, uuid(eda22a30-84e1-4e16-9ca0-cd1553c2b34a)] +[builtinclass, uuid(eda22a30-84e1-4e16-9ca0-cd1553c2b34a)] interface nsIGIOService : nsISupports { @@ -76,11 +77,9 @@ interface nsIGIOService : nsISupports /*** Misc. methods ***/ /* Open the given URI in the default application */ - void showURI(in nsIURI uri); - [noscript] void showURIForInput(in ACString uri); - - /* Open path in file manager using org.freedesktop.FileManager1 interface */ - [noscript] void orgFreedesktopFileManager1ShowItems(in ACString path); + [noscript] void showURI(in nsIURI uri); + [noscript] void revealFile(in nsIFile file); + [noscript] void launchFile(in ACString path); }; %{C++