LCOV - code coverage report
Current view: top level - toolkit/system/gnome - nsGIOService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 27 231 11.7 %
Date: 2017-07-14 16:53:18 Functions: 11 32 34.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsGIOService.h"
       7             : #include "nsString.h"
       8             : #include "nsIURI.h"
       9             : #include "nsTArray.h"
      10             : #include "nsIStringEnumerator.h"
      11             : #include "nsAutoPtr.h"
      12             : 
      13             : #include <gio/gio.h>
      14             : #include <gtk/gtk.h>
      15             : #ifdef MOZ_ENABLE_DBUS
      16             : #include <dbus/dbus-glib.h>
      17             : #include <dbus/dbus-glib-lowlevel.h>
      18             : #endif
      19             : 
      20             : 
      21             : class nsGIOMimeApp final : public nsIGIOMimeApp
      22             : {
      23             : public:
      24             :   NS_DECL_ISUPPORTS
      25             :   NS_DECL_NSIGIOMIMEAPP
      26             : 
      27           4 :   explicit nsGIOMimeApp(GAppInfo* aApp) : mApp(aApp) {}
      28             : 
      29             : private:
      30           4 :   ~nsGIOMimeApp() { g_object_unref(mApp); }
      31             : 
      32             :   GAppInfo *mApp;
      33             : };
      34             : 
      35          24 : NS_IMPL_ISUPPORTS(nsGIOMimeApp, nsIGIOMimeApp)
      36             : 
      37             : NS_IMETHODIMP
      38           0 : nsGIOMimeApp::GetId(nsACString& aId)
      39             : {
      40           0 :   aId.Assign(g_app_info_get_id(mApp));
      41           0 :   return NS_OK;
      42             : }
      43             : 
      44             : NS_IMETHODIMP
      45           4 : nsGIOMimeApp::GetName(nsACString& aName)
      46             : {
      47           4 :   aName.Assign(g_app_info_get_name(mApp));
      48           4 :   return NS_OK;
      49             : }
      50             : 
      51             : NS_IMETHODIMP
      52           0 : nsGIOMimeApp::GetCommand(nsACString& aCommand)
      53             : {
      54           0 :   const char *cmd = g_app_info_get_commandline(mApp);
      55           0 :   if (!cmd)
      56           0 :     return NS_ERROR_FAILURE;
      57           0 :   aCommand.Assign(cmd);
      58           0 :   return NS_OK;
      59             : }
      60             : 
      61             : NS_IMETHODIMP
      62           0 : nsGIOMimeApp::GetExpectsURIs(int32_t* aExpects)
      63             : {
      64           0 :   *aExpects = g_app_info_supports_uris(mApp);
      65           0 :   return NS_OK;
      66             : }
      67             : 
      68             : NS_IMETHODIMP
      69           0 : nsGIOMimeApp::Launch(const nsACString& aUri)
      70             : {
      71           0 :   GList uris = { 0 };
      72           0 :   nsPromiseFlatCString flatUri(aUri);
      73           0 :   uris.data = const_cast<char*>(flatUri.get());
      74             : 
      75           0 :   GError *error = nullptr;
      76           0 :   gboolean result = g_app_info_launch_uris(mApp, &uris, nullptr, &error);
      77             : 
      78           0 :   if (!result) {
      79           0 :     g_warning("Cannot launch application: %s", error->message);
      80           0 :     g_error_free(error);
      81           0 :     return NS_ERROR_FAILURE;
      82             :   }
      83             : 
      84           0 :   return NS_OK;
      85             : }
      86             : 
      87             : class GIOUTF8StringEnumerator final : public nsIUTF8StringEnumerator
      88             : {
      89           0 :   ~GIOUTF8StringEnumerator() = default;
      90             : 
      91             : public:
      92           0 :   GIOUTF8StringEnumerator() : mIndex(0) { }
      93             : 
      94             :   NS_DECL_ISUPPORTS
      95             :   NS_DECL_NSIUTF8STRINGENUMERATOR
      96             : 
      97             :   nsTArray<nsCString> mStrings;
      98             :   uint32_t            mIndex;
      99             : };
     100             : 
     101           0 : NS_IMPL_ISUPPORTS(GIOUTF8StringEnumerator, nsIUTF8StringEnumerator)
     102             : 
     103             : NS_IMETHODIMP
     104           0 : GIOUTF8StringEnumerator::HasMore(bool* aResult)
     105             : {
     106           0 :   *aResult = mIndex < mStrings.Length();
     107           0 :   return NS_OK;
     108             : }
     109             : 
     110             : NS_IMETHODIMP
     111           0 : GIOUTF8StringEnumerator::GetNext(nsACString& aResult)
     112             : {
     113           0 :   if (mIndex >= mStrings.Length())
     114           0 :     return NS_ERROR_UNEXPECTED;
     115             : 
     116           0 :   aResult.Assign(mStrings[mIndex]);
     117           0 :   ++mIndex;
     118           0 :   return NS_OK;
     119             : }
     120             : 
     121             : NS_IMETHODIMP
     122           0 : nsGIOMimeApp::GetSupportedURISchemes(nsIUTF8StringEnumerator** aSchemes)
     123             : {
     124           0 :   *aSchemes = nullptr;
     125             : 
     126           0 :   RefPtr<GIOUTF8StringEnumerator> array = new GIOUTF8StringEnumerator();
     127           0 :   NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
     128             : 
     129           0 :   GVfs *gvfs = g_vfs_get_default();
     130             : 
     131           0 :   if (!gvfs) {
     132           0 :     g_warning("Cannot get GVfs object.");
     133           0 :     return NS_ERROR_OUT_OF_MEMORY;
     134             :   }
     135             : 
     136           0 :   const gchar* const * uri_schemes = g_vfs_get_supported_uri_schemes(gvfs);
     137             : 
     138           0 :   while (*uri_schemes != nullptr) {
     139           0 :     if (!array->mStrings.AppendElement(*uri_schemes)) {
     140           0 :       return NS_ERROR_OUT_OF_MEMORY;
     141             :     }
     142           0 :     uri_schemes++;
     143             :   }
     144             : 
     145           0 :   array.forget(aSchemes);
     146           0 :   return NS_OK;
     147             : }
     148             : 
     149             : NS_IMETHODIMP
     150           0 : nsGIOMimeApp::SetAsDefaultForMimeType(nsACString const& aMimeType)
     151             : {
     152             :   char *content_type =
     153           0 :     g_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
     154           0 :   if (!content_type)
     155           0 :     return NS_ERROR_FAILURE;
     156           0 :   GError *error = nullptr;
     157           0 :   g_app_info_set_as_default_for_type(mApp,
     158             :                                      content_type,
     159           0 :                                      &error);
     160           0 :   if (error) {
     161           0 :     g_warning("Cannot set application as default for MIME type (%s): %s",
     162             :               PromiseFlatCString(aMimeType).get(),
     163           0 :               error->message);
     164           0 :     g_error_free(error);
     165           0 :     g_free(content_type);
     166           0 :     return NS_ERROR_FAILURE;
     167             :   }
     168             : 
     169           0 :   g_free(content_type);
     170           0 :   return NS_OK;
     171             : }
     172             : /**
     173             :  * Set default application for files with given extensions
     174             :  * @param fileExts string of space separated extensions
     175             :  * @return NS_OK when application was set as default for given extensions,
     176             :  * NS_ERROR_FAILURE otherwise
     177             :  */
     178             : NS_IMETHODIMP
     179           0 : nsGIOMimeApp::SetAsDefaultForFileExtensions(nsACString const& fileExts)
     180             : {
     181           0 :   GError *error = nullptr;
     182           0 :   char *extensions = g_strdup(PromiseFlatCString(fileExts).get());
     183           0 :   char *ext_pos = extensions;
     184             :   char *space_pos;
     185             : 
     186           0 :   while ( (space_pos = strchr(ext_pos, ' ')) || (*ext_pos != '\0') ) {
     187           0 :     if (space_pos) {
     188           0 :       *space_pos = '\0';
     189             :     }
     190           0 :     g_app_info_set_as_default_for_extension(mApp, ext_pos, &error);
     191           0 :     if (error) {
     192           0 :       g_warning("Cannot set application as default for extension (%s): %s",
     193             :                 ext_pos,
     194           0 :                 error->message);
     195           0 :       g_error_free(error);
     196           0 :       g_free(extensions);
     197           0 :       return NS_ERROR_FAILURE;
     198             :     }
     199           0 :     if (space_pos) {
     200           0 :       ext_pos = space_pos + 1;
     201             :     } else {
     202           0 :       *ext_pos = '\0';
     203             :     }
     204             :   }
     205           0 :   g_free(extensions);
     206           0 :   return NS_OK;
     207             : }
     208             : 
     209             : /**
     210             :  * Set default application for URI's of a particular scheme
     211             :  * @param aURIScheme string containing the URI scheme
     212             :  * @return NS_OK when application was set as default for URI scheme,
     213             :  * NS_ERROR_FAILURE otherwise
     214             :  */
     215             : NS_IMETHODIMP
     216           0 : nsGIOMimeApp::SetAsDefaultForURIScheme(nsACString const& aURIScheme)
     217             : {
     218           0 :   GError *error = nullptr;
     219           0 :   nsAutoCString contentType("x-scheme-handler/");
     220           0 :   contentType.Append(aURIScheme);
     221             : 
     222           0 :   g_app_info_set_as_default_for_type(mApp,
     223             :                                      contentType.get(),
     224           0 :                                      &error);
     225           0 :   if (error) {
     226           0 :     g_warning("Cannot set application as default for URI scheme (%s): %s",
     227             :               PromiseFlatCString(aURIScheme).get(),
     228           0 :               error->message);
     229           0 :     g_error_free(error);
     230           0 :     return NS_ERROR_FAILURE;
     231             :   }
     232             : 
     233           0 :   return NS_OK;
     234             : }
     235             : 
     236          15 : NS_IMPL_ISUPPORTS(nsGIOService, nsIGIOService)
     237             : 
     238             : NS_IMETHODIMP
     239           0 : nsGIOService::GetMimeTypeFromExtension(const nsACString& aExtension,
     240             :                                              nsACString& aMimeType)
     241             : {
     242           0 :   nsAutoCString fileExtToUse("file.");
     243           0 :   fileExtToUse.Append(aExtension);
     244             : 
     245             :   gboolean result_uncertain;
     246           0 :   char *content_type = g_content_type_guess(fileExtToUse.get(),
     247             :                                             nullptr,
     248             :                                             0,
     249           0 :                                             &result_uncertain);
     250           0 :   if (!content_type)
     251           0 :     return NS_ERROR_FAILURE;
     252             : 
     253           0 :   char *mime_type = g_content_type_get_mime_type(content_type);
     254           0 :   if (!mime_type) {
     255           0 :     g_free(content_type);
     256           0 :     return NS_ERROR_FAILURE;
     257             :   }
     258             : 
     259           0 :   aMimeType.Assign(mime_type);
     260             : 
     261           0 :   g_free(mime_type);
     262           0 :   g_free(content_type);
     263             : 
     264           0 :   return NS_OK;
     265             : }
     266             : // used in nsGNOMERegistry
     267             : // -----------------------------------------------------------------------------
     268             : NS_IMETHODIMP
     269           0 : nsGIOService::GetAppForURIScheme(const nsACString& aURIScheme,
     270             :                                  nsIGIOMimeApp** aApp)
     271             : {
     272           0 :   *aApp = nullptr;
     273             : 
     274           0 :   GAppInfo *app_info = g_app_info_get_default_for_uri_scheme(
     275           0 :                           PromiseFlatCString(aURIScheme).get());
     276           0 :   if (app_info) {
     277           0 :     nsGIOMimeApp *mozApp = new nsGIOMimeApp(app_info);
     278           0 :     NS_ADDREF(*aApp = mozApp);
     279             :   } else {
     280           0 :     return NS_ERROR_FAILURE;
     281             :   }
     282           0 :   return NS_OK;
     283             : }
     284             : 
     285             : NS_IMETHODIMP
     286           4 : nsGIOService::GetAppForMimeType(const nsACString& aMimeType,
     287             :                                 nsIGIOMimeApp**   aApp)
     288             : {
     289           4 :   *aApp = nullptr;
     290             :   char *content_type =
     291           4 :     g_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
     292           4 :   if (!content_type)
     293           0 :     return NS_ERROR_FAILURE;
     294             : 
     295           4 :   GAppInfo *app_info = g_app_info_get_default_for_type(content_type, false);
     296           4 :   if (app_info) {
     297           4 :     nsGIOMimeApp *mozApp = new nsGIOMimeApp(app_info);
     298           4 :     NS_ENSURE_TRUE(mozApp, NS_ERROR_OUT_OF_MEMORY);
     299           4 :     NS_ADDREF(*aApp = mozApp);
     300             :   } else {
     301           0 :     g_free(content_type);
     302           0 :     return NS_ERROR_FAILURE;
     303             :   }
     304           4 :   g_free(content_type);
     305           4 :   return NS_OK;
     306             : }
     307             : 
     308             : NS_IMETHODIMP
     309           4 : nsGIOService::GetDescriptionForMimeType(const nsACString& aMimeType,
     310             :                                               nsACString& aDescription)
     311             : {
     312             :   char *content_type =
     313           4 :     g_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
     314           4 :   if (!content_type)
     315           0 :     return NS_ERROR_FAILURE;
     316             : 
     317           4 :   char *desc = g_content_type_get_description(content_type);
     318           4 :   if (!desc) {
     319           0 :     g_free(content_type);
     320           0 :     return NS_ERROR_FAILURE;
     321             :   }
     322             : 
     323           4 :   aDescription.Assign(desc);
     324           4 :   g_free(content_type);
     325           4 :   g_free(desc);
     326           4 :   return NS_OK;
     327             : }
     328             : 
     329             : NS_IMETHODIMP
     330           0 : nsGIOService::ShowURI(nsIURI* aURI)
     331             : {
     332           0 :   nsAutoCString spec;
     333           0 :   nsresult rv = aURI->GetSpec(spec);
     334           0 :   NS_ENSURE_SUCCESS(rv, rv);
     335           0 :   GError *error = nullptr;
     336           0 :   if (!g_app_info_launch_default_for_uri(spec.get(), nullptr, &error)) {
     337           0 :     g_warning("Could not launch default application for URI: %s", error->message);
     338           0 :     g_error_free(error);
     339           0 :     return NS_ERROR_FAILURE;
     340             :   }
     341           0 :   return NS_OK;
     342             : }
     343             : 
     344             : NS_IMETHODIMP
     345           0 : nsGIOService::ShowURIForInput(const nsACString& aUri)
     346             : {
     347           0 :   GFile *file = g_file_new_for_commandline_arg(PromiseFlatCString(aUri).get());
     348           0 :   char* spec = g_file_get_uri(file);
     349           0 :   nsresult rv = NS_ERROR_FAILURE;
     350           0 :   GError *error = nullptr;
     351             : 
     352           0 :   g_app_info_launch_default_for_uri(spec, nullptr, &error);
     353           0 :   if (error) {
     354           0 :     g_warning("Cannot launch default application: %s", error->message);
     355           0 :     g_error_free(error);
     356             :   } else {
     357           0 :     rv = NS_OK;
     358             :   }
     359           0 :   g_object_unref(file);
     360           0 :   g_free(spec);
     361             : 
     362           0 :   return rv;
     363             : }
     364             : 
     365             : NS_IMETHODIMP
     366           0 : nsGIOService::OrgFreedesktopFileManager1ShowItems(const nsACString& aPath)
     367             : {
     368             : #ifndef MOZ_ENABLE_DBUS
     369             :   return NS_ERROR_FAILURE;
     370             : #else
     371           0 :   GError* error = nullptr;
     372             :   static bool org_freedesktop_FileManager1_exists = true;
     373             : 
     374           0 :   if (!org_freedesktop_FileManager1_exists) {
     375           0 :     return NS_ERROR_NOT_AVAILABLE;
     376             :   }
     377             : 
     378           0 :   DBusGConnection* dbusGConnection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
     379             : 
     380           0 :   if (!dbusGConnection) {
     381           0 :     if (error) {
     382           0 :       g_printerr("Failed to open connection to session bus: %s\n", error->message);
     383           0 :       g_error_free(error);
     384             :     }
     385           0 :     return NS_ERROR_FAILURE;
     386             :   }
     387             : 
     388           0 :   char *uri = g_filename_to_uri(PromiseFlatCString(aPath).get(), nullptr, nullptr);
     389           0 :   if (uri == nullptr) {
     390           0 :     return NS_ERROR_FAILURE;
     391             :   }
     392             : 
     393           0 :   DBusConnection* dbusConnection = dbus_g_connection_get_connection(dbusGConnection);
     394             :   // Make sure we do not exit the entire program if DBus connection get lost.
     395           0 :   dbus_connection_set_exit_on_disconnect(dbusConnection, false);
     396             : 
     397             :   DBusGProxy* dbusGProxy = dbus_g_proxy_new_for_name(dbusGConnection,
     398             :                                                      "org.freedesktop.FileManager1",
     399             :                                                      "/org/freedesktop/FileManager1",
     400           0 :                                                      "org.freedesktop.FileManager1");
     401             : 
     402           0 :   const char *uris[2] = { uri, nullptr };
     403           0 :   gboolean rv_dbus_call = dbus_g_proxy_call (dbusGProxy, "ShowItems", nullptr, G_TYPE_STRV, uris,
     404           0 :                                              G_TYPE_STRING, "", G_TYPE_INVALID, G_TYPE_INVALID);
     405             : 
     406           0 :   g_object_unref(dbusGProxy);
     407           0 :   dbus_g_connection_unref(dbusGConnection);
     408           0 :   g_free(uri);
     409             : 
     410           0 :   if (!rv_dbus_call) {
     411           0 :     org_freedesktop_FileManager1_exists = false;
     412           0 :     return NS_ERROR_NOT_AVAILABLE;
     413             :   }
     414             : 
     415           0 :   return NS_OK;
     416             : #endif
     417             : }
     418             : 
     419             : /**
     420             :  * Create or find already existing application info for specified command
     421             :  * and application name.
     422             :  * @param cmd command to execute
     423             :  * @param appName application name
     424             :  * @param appInfo location where created GAppInfo is stored
     425             :  * @return NS_OK when object is created, NS_ERROR_FAILURE otherwise.
     426             :  */
     427             : NS_IMETHODIMP
     428           0 : nsGIOService::CreateAppFromCommand(nsACString const& cmd,
     429             :                                    nsACString const& appName,
     430             :                                    nsIGIOMimeApp**   appInfo)
     431             : {
     432           0 :   GError *error = nullptr;
     433           0 :   *appInfo = nullptr;
     434             : 
     435           0 :   GAppInfo *app_info = nullptr, *app_info_from_list = nullptr;
     436           0 :   GList *apps = g_app_info_get_all();
     437           0 :   GList *apps_p = apps;
     438             : 
     439             :   // Try to find relevant and existing GAppInfo in all installed application
     440             :   // We do this by comparing each GAppInfo's executable with out own
     441           0 :   while (apps_p) {
     442           0 :     app_info_from_list = (GAppInfo*) apps_p->data;
     443           0 :     if (!app_info) {
     444             :       // If the executable is not absolute, get it's full path
     445           0 :       char *executable = g_find_program_in_path(g_app_info_get_executable(app_info_from_list));
     446             : 
     447           0 :       if (executable && strcmp(executable, PromiseFlatCString(cmd).get()) == 0) {
     448           0 :         g_object_ref (app_info_from_list);
     449           0 :         app_info = app_info_from_list;
     450             :       }
     451           0 :       g_free(executable);
     452             :     }
     453             : 
     454           0 :     g_object_unref(app_info_from_list);
     455           0 :     apps_p = apps_p->next;
     456             :   }
     457           0 :   g_list_free(apps);
     458             : 
     459           0 :   if (!app_info) {
     460           0 :     app_info = g_app_info_create_from_commandline(PromiseFlatCString(cmd).get(),
     461           0 :                                                   PromiseFlatCString(appName).get(),
     462             :                                                   G_APP_INFO_CREATE_SUPPORTS_URIS,
     463           0 :                                                   &error);
     464             :   }
     465             : 
     466           0 :   if (!app_info) {
     467           0 :     g_warning("Cannot create application info from command: %s", error->message);
     468           0 :     g_error_free(error);
     469           0 :     return NS_ERROR_FAILURE;
     470             :   }
     471           0 :   nsGIOMimeApp *mozApp = new nsGIOMimeApp(app_info);
     472           0 :   NS_ENSURE_TRUE(mozApp, NS_ERROR_OUT_OF_MEMORY);
     473           0 :   NS_ADDREF(*appInfo = mozApp);
     474           0 :   return NS_OK;
     475             : }

Generated by: LCOV version 1.13