Skip to content

Commit

Permalink
Bug 1762708 - Use async dbus for revealing files in nsGIOService. r=s…
Browse files Browse the repository at this point in the history
…transky

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
  • Loading branch information
emilio committed Apr 15, 2022
1 parent 810dd62 commit 5e3a231
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 64 deletions.
108 changes: 73 additions & 35 deletions toolkit/system/gnome/nsGIOService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -22,8 +23,7 @@
#include <gio/gio.h>
#include <gtk/gtk.h>
#ifdef MOZ_ENABLE_DBUS
# include <dbus/dbus-glib.h>
# include <dbus/dbus-glib-lowlevel.h>
# include "mozilla/widget/AsyncDBus.h"
#endif

using namespace mozilla;
Expand Down Expand Up @@ -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<GError> error;
if (!g_app_info_launch_default_for_uri(spec.get(), nullptr,
getter_Transfers(error))) {
Expand All @@ -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<GFile> file = dont_AddRef(
g_file_new_for_commandline_arg(PromiseFlatCString(aUri).get()));
g_file_new_for_commandline_arg(PromiseFlatCString(aPath).get()));
GUniquePtr<char> spec(g_file_get_uri(file));
GUniquePtr<GError> error;
g_app_info_launch_default_for_uri(spec.get(), nullptr,
Expand All @@ -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<GError> error;
RefPtr<GDBusProxy> 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<gchar> uri(
g_filename_to_uri(PromiseFlatCString(aPath).get(), nullptr, nullptr));
nsCOMPtr<nsIFile> 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<gchar> uri(g_filename_to_uri(path.get(), nullptr, nullptr));
if (!uri) {
RevealDirectory(aFile, /* aForce = */ true);
return NS_ERROR_FAILURE;
}

Expand All @@ -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<GVariant> 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<GVariant>&& aResult) {
// Do nothing, file is shown, we're done.
},
[file = RefPtr{aFile}](GUniquePtr<GError>&& 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<GDBusProxy>&& aProxy) {
RevealFileViaDBusWithProxy(aProxy.get(), file);
},
[file = RefPtr{aFile}](GUniquePtr<GError>&& 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
}

Expand Down
25 changes: 2 additions & 23 deletions xpcom/io/nsLocalFileUnix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<nsIFile> 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))) {
Expand All @@ -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;
Expand Down
11 changes: 5 additions & 6 deletions xpcom/system/nsIGIOService.idl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

interface nsIUTF8StringEnumerator;
interface nsIURI;
interface nsIFile;
interface nsIMutableArray;

/* nsIGIOMimeApp holds information about an application that is looked up
Expand Down Expand 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
{

Expand Down Expand Up @@ -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++
Expand Down

0 comments on commit 5e3a231

Please sign in to comment.