зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1411579 - add system handler when Firefox runs in flatpak; r=stransky
Firefox in Flatpak sandboxed environment does not get the list of installed applications on the system because application should know about the environment as little as possible. Introducing nsFlatpakHandlerApp which forwards requests for opening downloaded files to the system by utilizing gtk_show_uri fuction. This changeset also removes nsIGIOMimeApp::Launch method from the interface because it can be fully replaced with LaunchWithUri from nsIHandlerApp interface. The TMPDIR where files are downloaded when user choose to open them needs to be accessible from sandbox and host. The default settings TMPDIR=/tmp is accessible only to the sandbox. To workaround for is to set TMPDIR environment variable to $XDG_CACHE_HOME/tmp before executing Firefox. MozReview-Commit-ID: CSBv0QcETpd --HG-- extra : rebase_source : 8155c33fa9c402d2668bdfb07094ba6758fe6203
This commit is contained in:
Родитель
927ea89c0d
Коммит
e55996cc86
|
@ -229,8 +229,10 @@ nsGNOMEShellService::IsDefaultBrowser(bool aStartupCheck,
|
|||
|
||||
if (giovfs) {
|
||||
handler.Truncate();
|
||||
nsCOMPtr<nsIHandlerApp> handlerApp;
|
||||
giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name),
|
||||
getter_AddRefs(gioApp));
|
||||
getter_AddRefs(handlerApp));
|
||||
gioApp = do_QueryInterface(handlerApp);
|
||||
if (!gioApp)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -571,10 +573,10 @@ nsGNOMEShellService::OpenApplication(int32_t aApplication)
|
|||
|
||||
nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
|
||||
if (giovfs) {
|
||||
nsCOMPtr<nsIGIOMimeApp> gioApp;
|
||||
giovfs->GetAppForURIScheme(scheme, getter_AddRefs(gioApp));
|
||||
if (gioApp)
|
||||
return gioApp->Launch(EmptyCString());
|
||||
nsCOMPtr<nsIHandlerApp> handlerApp;
|
||||
giovfs->GetAppForURIScheme(scheme, getter_AddRefs(handlerApp));
|
||||
if (handlerApp)
|
||||
return handlerApp->LaunchWithURI(nullptr, nullptr);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsArray.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
@ -21,6 +22,93 @@
|
|||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#endif
|
||||
|
||||
// We use the same code as gtk_should_use_portal() to detect if we're in flatpak env
|
||||
// https://github.com/GNOME/gtk/blob/e0ce028c88858b96aeda9e41734a39a3a04f705d/gtk/gtkprivate.c#L272
|
||||
static bool GetShouldUseFlatpakPortal() {
|
||||
bool shouldUsePortal;
|
||||
char *path;
|
||||
path = g_build_filename(g_get_user_runtime_dir(), "flatpak-info", nullptr);
|
||||
if (g_file_test(path, G_FILE_TEST_EXISTS)) {
|
||||
shouldUsePortal = true;
|
||||
} else {
|
||||
shouldUsePortal = (g_getenv("GTK_USE_PORTAL") != nullptr);
|
||||
}
|
||||
g_free(path);
|
||||
return shouldUsePortal;
|
||||
}
|
||||
|
||||
static bool ShouldUseFlatpakPortal() {
|
||||
static bool sShouldUseFlatpakPortal = GetShouldUseFlatpakPortal();
|
||||
return sShouldUseFlatpakPortal;
|
||||
}
|
||||
|
||||
class nsFlatpakHandlerApp : public nsIHandlerApp
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIHANDLERAPP
|
||||
nsFlatpakHandlerApp() = default;
|
||||
private:
|
||||
virtual ~nsFlatpakHandlerApp() = default;
|
||||
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsFlatpakHandlerApp, nsIHandlerApp)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFlatpakHandlerApp::GetName(nsAString& aName)
|
||||
{
|
||||
aName.AssignLiteral("System Handler");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFlatpakHandlerApp::SetName(const nsAString& aName)
|
||||
{
|
||||
// We don't implement SetName because flatpak system handler name is fixed
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFlatpakHandlerApp::GetDetailedDescription(nsAString& aDetailedDescription)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFlatpakHandlerApp::SetDetailedDescription(const nsAString& aDetailedDescription)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFlatpakHandlerApp::Equals(nsIHandlerApp* aHandlerApp, bool* _retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFlatpakHandlerApp::LaunchWithURI(nsIURI* aUri, nsIInterfaceRequestor* aRequestor)
|
||||
{
|
||||
nsCString spec;
|
||||
aUri->GetSpec(spec);
|
||||
GError *error = nullptr;
|
||||
|
||||
// The TMPDIR where files are downloaded when user choose to open them
|
||||
// needs to be accessible from sandbox and host. The default settings
|
||||
// TMPDIR=/tmp is accessible only to the sandbox. That can be the reason
|
||||
// why the gtk_show_uri fails there.
|
||||
// The workaround is to set TMPDIR environment variable in sandbox to
|
||||
// $XDG_CACHE_HOME/tmp before executing Firefox.
|
||||
gtk_show_uri(nullptr, spec.get(), GDK_CURRENT_TIME, &error);
|
||||
if (error) {
|
||||
NS_WARNING(nsPrintfCString("Cannot launch flatpak handler: %s",
|
||||
error->message).get());
|
||||
g_error_free(error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get command without any additional arguments
|
||||
|
@ -100,25 +188,6 @@ nsGIOMimeApp::GetExpectsURIs(int32_t* aExpects)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGIOMimeApp::Launch(const nsACString& aUri)
|
||||
{
|
||||
GList uris = { 0 };
|
||||
nsPromiseFlatCString flatUri(aUri);
|
||||
uris.data = const_cast<char*>(flatUri.get());
|
||||
|
||||
GError *error = nullptr;
|
||||
gboolean result = g_app_info_launch_uris(mApp, &uris, nullptr, &error);
|
||||
|
||||
if (!result) {
|
||||
g_warning("Cannot launch application: %s", error->message);
|
||||
g_error_free(error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGIOMimeApp::GetDetailedDescription(nsAString& aDetailedDescription)
|
||||
{
|
||||
|
@ -179,9 +248,22 @@ nsGIOMimeApp::Equals(nsIHandlerApp* aHandlerApp, bool* _retval)
|
|||
NS_IMETHODIMP
|
||||
nsGIOMimeApp::LaunchWithURI(nsIURI* aUri, nsIInterfaceRequestor* aRequestor)
|
||||
{
|
||||
nsCString uri_string;
|
||||
aUri->GetSpec(uri_string);
|
||||
return Launch(uri_string);
|
||||
GList uris = { 0 };
|
||||
nsCString spec;
|
||||
aUri->GetSpec(spec);
|
||||
//nsPromiseFlatCString flatUri(aUri);
|
||||
uris.data = const_cast<char*>(spec.get());
|
||||
|
||||
GError *error = nullptr;
|
||||
gboolean result = g_app_info_launch_uris(mApp, &uris, nullptr, &error);
|
||||
|
||||
if (!result) {
|
||||
g_warning("Cannot launch application: %s", error->message);
|
||||
g_error_free(error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class GIOUTF8StringEnumerator final : public nsIUTF8StringEnumerator
|
||||
|
@ -367,10 +449,19 @@ nsGIOService::GetMimeTypeFromExtension(const nsACString& aExtension,
|
|||
// -----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsGIOService::GetAppForURIScheme(const nsACString& aURIScheme,
|
||||
nsIGIOMimeApp** aApp)
|
||||
nsIHandlerApp** aApp)
|
||||
{
|
||||
*aApp = nullptr;
|
||||
|
||||
// Application in flatpak sandbox does not have access to the list
|
||||
// of installed applications on the system. We use generic
|
||||
// nsFlatpakHandlerApp which forwards launch call to the system.
|
||||
if (ShouldUseFlatpakPortal()) {
|
||||
nsFlatpakHandlerApp *mozApp = new nsFlatpakHandlerApp();
|
||||
NS_ADDREF(*aApp = mozApp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GAppInfo *app_info = g_app_info_get_default_for_uri_scheme(
|
||||
PromiseFlatCString(aURIScheme).get());
|
||||
if (app_info) {
|
||||
|
@ -386,6 +477,13 @@ NS_IMETHODIMP
|
|||
nsGIOService::GetAppsForURIScheme(const nsACString& aURIScheme,
|
||||
nsIMutableArray** aResult)
|
||||
{
|
||||
// We don't need to return the nsFlatpakHandlerApp here because
|
||||
// it would be skipped by the callers anyway.
|
||||
// The preferred handler is provided by GetAppForURIScheme.
|
||||
// This method returns all possible application handlers
|
||||
// including preferred one. The callers skips the preferred
|
||||
// handler in this list to avoid duplicate records in the list
|
||||
// they create.
|
||||
nsCOMPtr<nsIMutableArray> handlersArray =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
|
||||
|
@ -411,9 +509,18 @@ nsGIOService::GetAppsForURIScheme(const nsACString& aURIScheme,
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsGIOService::GetAppForMimeType(const nsACString& aMimeType,
|
||||
nsIGIOMimeApp** aApp)
|
||||
nsIHandlerApp** aApp)
|
||||
{
|
||||
*aApp = nullptr;
|
||||
|
||||
// Flatpak does not reveal installed application to the sandbox,
|
||||
// we need to create generic system handler.
|
||||
if (ShouldUseFlatpakPortal()) {
|
||||
nsFlatpakHandlerApp *mozApp = new nsFlatpakHandlerApp();
|
||||
NS_ADDREF(*aApp = mozApp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
char *content_type =
|
||||
g_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
|
||||
if (!content_type)
|
||||
|
|
|
@ -18,7 +18,7 @@ nsGNOMERegistry::HandlerExists(const char *aProtocolScheme)
|
|||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGIOMimeApp> app;
|
||||
nsCOMPtr<nsIHandlerApp> app;
|
||||
return NS_SUCCEEDED(giovfs->GetAppForURIScheme(nsDependentCString(aProtocolScheme),
|
||||
getter_AddRefs(app)));
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ nsGNOMERegistry::GetAppDescForScheme(const nsACString& aScheme,
|
|||
if (!giovfs)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIGIOMimeApp> app;
|
||||
nsCOMPtr<nsIHandlerApp> app;
|
||||
if (NS_FAILED(giovfs->GetAppForURIScheme(aScheme, getter_AddRefs(app))))
|
||||
return;
|
||||
|
||||
|
@ -90,12 +90,12 @@ nsGNOMERegistry::GetFromType(const nsACString& aMIMEType)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGIOMimeApp> gioHandlerApp;
|
||||
if (NS_FAILED(giovfs->GetAppForMimeType(aMIMEType, getter_AddRefs(gioHandlerApp))) ||
|
||||
!gioHandlerApp) {
|
||||
nsCOMPtr<nsIHandlerApp> handlerApp;
|
||||
if (NS_FAILED(giovfs->GetAppForMimeType(aMIMEType, getter_AddRefs(handlerApp))) ||
|
||||
!handlerApp) {
|
||||
return nullptr;
|
||||
}
|
||||
gioHandlerApp->GetName(name);
|
||||
handlerApp->GetName(name);
|
||||
giovfs->GetDescriptionForMimeType(aMIMEType, description);
|
||||
|
||||
mimeInfo->SetDefaultDescription(name);
|
||||
|
|
|
@ -76,14 +76,12 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(nsIFile *aFile)
|
|||
nsCOMPtr<nsIURI> uri;
|
||||
rv = ioservice->NewFileURI(aFile, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoCString uriSpec;
|
||||
uri->GetSpec(uriSpec);
|
||||
|
||||
nsCOMPtr<nsIGIOMimeApp> app;
|
||||
nsCOMPtr<nsIHandlerApp> app;
|
||||
if (NS_FAILED(giovfs->GetAppForMimeType(mSchemeOrType, getter_AddRefs(app))) || !app) {
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return app->Launch(uriSpec);
|
||||
return app->LaunchWithURI(uri, nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -391,6 +391,7 @@ STUB(gtk_separator_menu_item_new)
|
|||
STUB(gtk_separator_tool_item_new)
|
||||
STUB(gtk_settings_get_default)
|
||||
STUB(gtk_settings_get_for_screen)
|
||||
STUB(gtk_show_uri)
|
||||
STUB(gtk_socket_add_id)
|
||||
STUB(gtk_socket_get_id)
|
||||
STUB(gtk_socket_get_type)
|
||||
|
|
|
@ -26,7 +26,6 @@ interface nsIGIOMimeApp : nsIHandlerApp
|
|||
readonly attribute long expectsURIs; // see constants above
|
||||
readonly attribute nsIUTF8StringEnumerator supportedURISchemes;
|
||||
|
||||
void launch(in AUTF8String uri);
|
||||
void setAsDefaultForMimeType(in AUTF8String mimeType);
|
||||
void setAsDefaultForFileExtensions(in AUTF8String extensions);
|
||||
void setAsDefaultForURIScheme(in AUTF8String uriScheme);
|
||||
|
@ -56,13 +55,13 @@ interface nsIGIOService : nsISupports
|
|||
AUTF8String getMimeTypeFromExtension(in AUTF8String extension);
|
||||
|
||||
/* Obtain the preferred application for opening a given URI scheme */
|
||||
nsIGIOMimeApp getAppForURIScheme(in AUTF8String aURIScheme);
|
||||
nsIHandlerApp getAppForURIScheme(in AUTF8String aURIScheme);
|
||||
|
||||
/* Obtain list of application capable of opening given URI scheme */
|
||||
nsIMutableArray getAppsForURIScheme(in AUTF8String aURIScheme);
|
||||
|
||||
/* Obtain the preferred application for opening a given MIME type */
|
||||
nsIGIOMimeApp getAppForMimeType(in AUTF8String mimeType);
|
||||
nsIHandlerApp getAppForMimeType(in AUTF8String mimeType);
|
||||
|
||||
/* Create application info for given command and name */
|
||||
nsIGIOMimeApp createAppFromCommand(in AUTF8String cmd,
|
||||
|
|
Загрузка…
Ссылка в новой задаче