LCOV - code coverage report
Current view: top level - toolkit/system/gnome - nsPackageKitService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 90 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 11 0.0 %
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 "nsArrayUtils.h"
       7             : #include "nsIObserver.h"
       8             : #include "nsIObserverService.h"
       9             : #include "nsISupportsPrimitives.h"
      10             : #include "nsPackageKitService.h"
      11             : #include "nsString.h"
      12             : #include "prlink.h"
      13             : #include "mozilla/Unused.h"
      14             : #include "mozilla/UniquePtr.h"
      15             : 
      16             : #include <glib.h>
      17             : #include <glib-object.h>
      18             : #include <limits>
      19             : 
      20             : using namespace mozilla;
      21             : 
      22             : typedef struct _GAsyncResult GAsyncResult;
      23             : typedef enum {
      24             :   G_BUS_TYPE_STARTER = -1,
      25             :   G_BUS_TYPE_NONE = 0,
      26             :   G_BUS_TYPE_SYSTEM  = 1,
      27             :   G_BUS_TYPE_SESSION = 2
      28             : } GBusType;
      29             : typedef struct _GCancellable GCancellable;
      30             : typedef enum {
      31             :   G_DBUS_CALL_FLAGS_NONE = 0,
      32             :   G_DBUS_CALL_FLAGS_NO_AUTO_START = (1<<0)
      33             : } GDBusCallFlags;
      34             : typedef struct _GDBusInterfaceInfo GDBusInterfaceInfo;
      35             : typedef struct _GDBusProxy GDBusProxy;
      36             : typedef enum {
      37             :   G_DBUS_PROXY_FLAGS_NONE = 0,
      38             :   G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES = (1<<0),
      39             :   G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS = (1<<1),
      40             :   G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START = (1<<2),
      41             :   G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES = (1<<3)
      42             : } GDBusProxyFlags;
      43             : typedef struct _GVariant GVariant;
      44             : typedef void (*GAsyncReadyCallback) (GObject *source_object,
      45             :                                      GAsyncResult *res,
      46             :                                      gpointer user_data);
      47             : 
      48             : #define GDBUS_FUNCTIONS \
      49             :   FUNC(g_dbus_proxy_call, void, (GDBusProxy *proxy, const gchar *method_name, GVariant *parameters, GDBusCallFlags flags, gint timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)) \
      50             :   FUNC(g_dbus_proxy_call_finish, GVariant*, (GDBusProxy *proxy, GAsyncResult *res, GError **error)) \
      51             :   FUNC(g_dbus_proxy_new_finish, GDBusProxy*, (GAsyncResult *res, GError **error)) \
      52             :   FUNC(g_dbus_proxy_new_for_bus, void, (GBusType bus_type, GDBusProxyFlags flags, GDBusInterfaceInfo *info, const gchar *name, const gchar *object_path, const gchar *interface_name,  GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)) \
      53             :   FUNC(g_variant_is_floating, gboolean, (GVariant *value)) \
      54             :   FUNC(g_variant_new, GVariant*, (const gchar *format_string, ...)) \
      55             :   FUNC(g_variant_unref, void, (GVariant* value))
      56             : 
      57             : #define FUNC(name, type, params) \
      58             :   typedef type (*_##name##_fn) params; \
      59             :   static _##name##_fn _##name;
      60             : 
      61             : GDBUS_FUNCTIONS
      62             : 
      63             : #undef FUNC
      64             : 
      65             : #define g_dbus_proxy_call _g_dbus_proxy_call
      66             : #define g_dbus_proxy_call_finish _g_dbus_proxy_call_finish
      67             : #define g_dbus_proxy_new_finish _g_dbus_proxy_new_finish
      68             : #define g_dbus_proxy_new_for_bus _g_dbus_proxy_new_for_bus
      69             : #define g_variant_is_floating _g_variant_is_floating
      70             : #define g_variant_new _g_variant_new
      71             : #define g_variant_unref _g_variant_unref
      72             : 
      73             : static PRLibrary *gioLib = nullptr;
      74             : 
      75             : typedef void (*nsGDBusFunc)();
      76             : struct nsGDBusDynamicFunction {
      77             :   const char *functionName;
      78             :   nsGDBusFunc *function;
      79             : };
      80             : 
      81             : nsresult
      82           0 : nsPackageKitService::Init()
      83             : {
      84             : #define FUNC(name, type, params) { #name, (nsGDBusFunc *)&_##name },
      85             :   const nsGDBusDynamicFunction kGDBusSymbols[] = {
      86             :     GDBUS_FUNCTIONS
      87           0 :   };
      88             : #undef FUNC
      89             : 
      90           0 :   if (!gioLib) {
      91           0 :     gioLib = PR_LoadLibrary("libgio-2.0.so.0");
      92           0 :     if (!gioLib)
      93           0 :       return NS_ERROR_FAILURE;
      94             :   }
      95             : 
      96           0 :   for (auto GDBusSymbol : kGDBusSymbols) {
      97           0 :     *GDBusSymbol.function =
      98           0 :       PR_FindFunctionSymbol(gioLib, GDBusSymbol.functionName);
      99           0 :     if (!*GDBusSymbol.function) {
     100           0 :       return NS_ERROR_FAILURE;
     101             :     }
     102             :   }
     103             : 
     104           0 :   return NS_OK;
     105             : }
     106             : 
     107           0 : NS_IMPL_ISUPPORTS(nsPackageKitService, nsIPackageKitService)
     108             : 
     109           0 : nsPackageKitService::~nsPackageKitService()
     110             : {
     111           0 :   if (gioLib) {
     112           0 :     PR_UnloadLibrary(gioLib);
     113           0 :     gioLib = nullptr;
     114             :   }
     115           0 : }
     116             : 
     117             : static const char* InstallPackagesMethods[] = {
     118             :   "InstallPackageNames",
     119             :   "InstallMimeTypes",
     120             :   "InstallFontconfigResources",
     121             :   "InstallGStreamerResources"
     122             : };
     123             : 
     124           0 : struct InstallPackagesProxyNewData {
     125             :   nsCOMPtr<nsIObserver> observer;
     126             :   uint32_t method;
     127             :   GVariant* parameters;
     128             : };
     129             : 
     130             : static void
     131           0 : InstallPackagesNotifyObserver(nsIObserver* aObserver,
     132             :                               gchar* aErrorMessage)
     133             : {
     134           0 :   if (aObserver) {
     135           0 :     aObserver->Observe(nullptr, "packagekit-install",
     136             :                        aErrorMessage ?
     137           0 :                        NS_ConvertUTF8toUTF16(aErrorMessage).get() :
     138           0 :                        nullptr);
     139             :   }
     140           0 : }
     141             : 
     142             : static void
     143           0 : InstallPackagesProxyCallCallback(GObject *aSourceObject,
     144             :                                  GAsyncResult *aResult,
     145             :                                  gpointer aUserData)
     146             : {
     147           0 :   nsCOMPtr<nsIObserver> observer = static_cast<nsIObserver*>(aUserData);
     148           0 :   GDBusProxy* proxy = reinterpret_cast<GDBusProxy*>(aSourceObject);
     149             : 
     150           0 :   GError* error = nullptr;
     151           0 :   GVariant* result = g_dbus_proxy_call_finish(proxy, aResult, &error);
     152           0 :   if (result) {
     153           0 :     InstallPackagesNotifyObserver(observer, nullptr);
     154           0 :     g_variant_unref(result);
     155             :   } else {
     156           0 :     NS_ASSERTION(error, "g_dbus_proxy_call_finish should set error when it returns NULL");
     157           0 :     InstallPackagesNotifyObserver(observer, error->message);
     158           0 :     g_error_free(error);
     159             :   }
     160             : 
     161           0 :   g_object_unref(proxy);
     162           0 :   Unused << observer.forget().take();
     163           0 : }
     164             : 
     165             : static void
     166           0 : InstallPackagesProxyNewCallback(GObject *aSourceObject,
     167             :                                 GAsyncResult *aResult,
     168             :                                 gpointer aUserData)
     169             : {
     170             :   InstallPackagesProxyNewData* userData =
     171           0 :     static_cast<InstallPackagesProxyNewData*>(aUserData);
     172             : 
     173           0 :   NS_ASSERTION(g_variant_is_floating(userData->parameters),
     174             :                "userData->parameters should be a floating reference.");
     175             : 
     176           0 :   GError* error = nullptr;
     177           0 :   GDBusProxy* proxy = g_dbus_proxy_new_finish(aResult, &error);
     178             : 
     179           0 :   if (proxy) {
     180             :     // Send the asynchronous request to install the packages
     181             :     // This call will consume the floating reference userData->parameters so we
     182             :     // don't need to release it explicitly.
     183             :     nsIObserver* observer;
     184           0 :     userData->observer.forget(&observer);
     185           0 :     g_dbus_proxy_call(proxy,
     186           0 :                       InstallPackagesMethods[userData->method],
     187             :                       userData->parameters,
     188             :                       G_DBUS_CALL_FLAGS_NONE,
     189             :                       G_MAXINT,
     190             :                       nullptr,
     191             :                       &InstallPackagesProxyCallCallback,
     192           0 :                       static_cast<gpointer>(observer));
     193             :   } else {
     194           0 :     NS_ASSERTION(error, "g_dbus_proxy_new_finish should set error when it returns NULL");
     195           0 :     InstallPackagesNotifyObserver(userData->observer, error->message);
     196           0 :     g_error_free(error);
     197           0 :     g_variant_unref(userData->parameters);
     198             :   }
     199           0 :   delete userData;
     200           0 : }
     201             : 
     202             : NS_IMETHODIMP
     203           0 : nsPackageKitService::InstallPackages(uint32_t aInstallMethod,
     204             :                                      nsIArray* aPackageArray,
     205             :                                      nsIObserver* aObserver)
     206             : {
     207           0 :   NS_ENSURE_ARG(aPackageArray);
     208             : 
     209             :   uint32_t arrayLength;
     210           0 :   aPackageArray->GetLength(&arrayLength);
     211           0 :   if (arrayLength == 0 ||
     212           0 :       arrayLength == std::numeric_limits<uint32_t>::max() ||
     213             :       aInstallMethod >= PK_INSTALL_METHOD_COUNT) {
     214           0 :     return NS_ERROR_INVALID_ARG;
     215             :   }
     216             : 
     217             :   // Create the GVariant* parameter from the list of packages.
     218           0 :   GVariant* parameters = nullptr;
     219           0 :   auto packages = MakeUnique<gchar*[]>(arrayLength + 1);
     220             : 
     221           0 :   nsresult rv = NS_OK;
     222           0 :   for (uint32_t i = 0; i < arrayLength; i++) {
     223             :     nsCOMPtr<nsISupportsString> package =
     224           0 :       do_QueryElementAt(aPackageArray, i);
     225           0 :     if (!package) {
     226           0 :       rv = NS_ERROR_FAILURE;
     227           0 :       break;
     228             :     }
     229           0 :     nsString data;
     230           0 :     package->GetData(data);
     231           0 :     packages[i] = g_strdup(NS_ConvertUTF16toUTF8(data).get());
     232           0 :     if (!packages[i]) {
     233           0 :       rv = NS_ERROR_OUT_OF_MEMORY;
     234           0 :       break;
     235             :     }
     236             :   }
     237           0 :   packages[arrayLength] = nullptr;
     238             : 
     239           0 :   if (NS_SUCCEEDED(rv)) {
     240             :     // We create a new GVariant object to send parameters to PackageKit.
     241           0 :     parameters = g_variant_new("(u^ass)", static_cast<guint32>(0),
     242           0 :                                packages.get(), "hide-finished");
     243           0 :     if (!parameters) {
     244           0 :       rv = NS_ERROR_OUT_OF_MEMORY;
     245             :     }
     246             :   }
     247           0 :   for (uint32_t i = 0; i < arrayLength; i++) {
     248           0 :     g_free(packages[i]);
     249             :   }
     250           0 :   NS_ENSURE_SUCCESS(rv, rv);
     251             : 
     252             :   // Send the asynchronous request to load the bus proxy
     253           0 :   InstallPackagesProxyNewData* data = new InstallPackagesProxyNewData;
     254           0 :   data->observer = aObserver;
     255           0 :   data->method = aInstallMethod;
     256           0 :   data->parameters = parameters;
     257             :   g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
     258             :                            G_DBUS_PROXY_FLAGS_NONE,
     259             :                            nullptr,
     260             :                            "org.freedesktop.PackageKit",
     261             :                            "/org/freedesktop/PackageKit",
     262             :                            "org.freedesktop.PackageKit.Modify",
     263             :                            nullptr,
     264             :                            &InstallPackagesProxyNewCallback,
     265           0 :                            static_cast<gpointer>(data));
     266           0 :   return NS_OK;
     267             : }

Generated by: LCOV version 1.13