LibreOffice in a Box

I had the pleasure of presenting my initial work on packaging LibreOffice as a sandboxed xdg-app bundle at GUADEC over the weekend.

Additionally, I dumped my experimental xdg-app repo for my LibreOffice build at http://people.redhat.com/sbergman/lo-repo now.  It is built off the current libreoffice-5-0-1 branch, with an autogen.input consisting of

--disable-odk
--disable-ooenv
--disable-systray
--enable-gtk3
--enable-release-build
--enable-werror
--disable-cups
--disable-gconf
--disable-gltf
--disable-gstreamer-1-0
--disable-orcus
--disable-postgresql_sdbc
--without-java
--with-system-libs
--without-system-altlinuxhyph
--without-system-bluez
--without-system-boost
--without-system-clucene
--without-system-coinmp
--without-system-cppunit
--without-system-curl
--without-system-firebird
--without-system-glew
--without-system-glm
--without-system-libabw
--without-system-libcdr
--without-system-libcmis
--without-system-libebook
--without-system-libetonyek
--without-system-libexttextcat
--without-system-libfreehand
--without-system-liblangtag
--without-system-libmspub
--without-system-libmwaw
--without-system-libodfgen
--without-system-libpagemaker
--without-system-librevenge
--without-system-libvisio
--without-system-libwpd
--without-system-libwpg
--without-system-libwps
--without-system-lpsolve
--without-system-mdds
--without-system-mythes
--without-system-neon
--without-system-npapi-headers
--without-system-odbc
--without-system-openldap
--without-system-poppler
--without-system-redland
--without-system-sane
--without-system-vigra

and some local patch

diff --git a/external/redland/ExternalProject_raptor.mk b/external/redland/ExternalProject_raptor.mk
index eaffcf1..dbc0649 100644
--- a/external/redland/ExternalProject_raptor.mk
+++ b/external/redland/ExternalProject_raptor.mk
@@ -48,7 +48,7 @@ $(call gb_ExternalProject_get_state_target,raptor,build):
 			$(if $(CROSS_COMPILING),--build=$(BUILD_PLATFORM) --host=$(HOST_PLATFORM)) \
 			$(if $(filter MACOSX,$(OS)),--prefix=/@.__________________________________________________OOO) \
 			$(if $(filter IOS ANDROID,$(OS)),--disable-shared,--disable-static) \
-			$(if $(SYSTEM_LIBXML),,--with-xml2-config=$(call gb_UnpackedTarball_get_dir,xml2)/xml2-config) \
+			$(if $(SYSTEM_LIBXML),--without-xml2-config,--with-xml2-config=$(call gb_UnpackedTarball_get_dir,xml2)/xml2-config) \
 		&& $(MAKE) \
 	)
 endif
diff --git a/fpicker/Library_fps_office.mk b/fpicker/Library_fps_office.mk
index c109dce..7ce952d 100644
--- a/fpicker/Library_fps_office.mk
+++ b/fpicker/Library_fps_office.mk
@@ -13,6 +13,7 @@ $(eval $(call gb_Library_Library,fps_office))
 $(eval $(call gb_Library_set_componentfile,fps_office,fpicker/source/office/fps_office))
 
 $(eval $(call gb_Library_use_external,fps_office,boost_headers))
+$(eval $(call gb_Library_use_external,fps_office,gio))
 
 $(eval $(call gb_Library_use_custom_headers,fps_office,\
 	officecfg/registry \
diff --git a/fpicker/source/office/OfficeFilePicker.cxx b/fpicker/source/office/OfficeFilePicker.cxx
index 6fd28ed..40698aa 100644
--- a/fpicker/source/office/OfficeFilePicker.cxx
+++ b/fpicker/source/office/OfficeFilePicker.cxx
@@ -43,6 +43,8 @@
 #include "osl/mutex.hxx"
 #include "vcl/svapp.hxx"
 
+#include <gio/gio.h>
+
 // using ----------------------------------------------------------------
 
 using namespace     ::com::sun::star::container;
@@ -504,29 +506,71 @@ void SAL_CALL SvtFilePicker::setTitle( const OUString& _rTitle ) throw (RuntimeE
 
 sal_Int16 SAL_CALL SvtFilePicker::execute(  ) throw (RuntimeException, std::exception)
 {
-    return OCommonPicker::execute();
-}
-
-
-// XAsynchronousExecutableDialog functions
-
-
-
-void SAL_CALL SvtFilePicker::setDialogTitle( const OUString& _rTitle ) throw (RuntimeException, std::exception)
-{
-    setTitle( _rTitle );
-}
-
-
-void SAL_CALL SvtFilePicker::startExecuteModal( const Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener >& xListener )
-    throw (RuntimeException,
-           std::exception)
-{
-    m_xDlgClosedListener = xListener;
-    prepareDialog();
-    prepareExecute();
-    getDialog()->EnableAutocompletion( true );
-    getDialog()->StartExecuteModal( LINK( this, SvtFilePicker, DialogClosedHdl ) );
+    GError * err = nullptr;
+    GDBusProxy * proxy = g_dbus_proxy_new_for_bus_sync(
+        G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, nullptr,
+        "org.freedesktop.portal.ContentPortal",
+        "/org/freedesktop/portal/content",
+        "org.freedesktop.portal.ContentPortal", nullptr, &err);
+    if (proxy == nullptr) {
+        assert(err != nullptr);
+        SAL_DEBUG("GError " << g_quark_to_string(err->domain) << " " << err->code << " " << err->message);
+        g_clear_error(&err);
+        std::abort();
+    }
+    assert(err == nullptr);
+    GVariant * ret = g_dbus_proxy_call_sync(
+        proxy, "Open", g_variant_new("(as)", nullptr), G_DBUS_CALL_FLAGS_NONE,
+        G_MAXINT, nullptr, &err);
+    bool cncl = false;
+    OUString id;
+    if (ret == nullptr) {
+        assert(err != nullptr);
+        cncl = g_error_matches(err, g_io_error_quark(), G_IO_ERROR_DBUS_ERROR);
+        if (!cncl) {
+            SAL_DEBUG("GError " << g_quark_to_string(err->domain) << " " << err->code << " " << err->message);
+            std::abort();
+        }
+        g_clear_error(&err);
+    } else {
+        //TODO type check
+        GVariant * v = g_variant_get_child_value(ret, 0);
+        gsize len;
+#if 0
+        gchar const * s = g_variant_get_string(v, &len);
+#else
+        gconstpointer p = g_variant_get_fixed_array(v, &len, 1);
+        char const * s = static_cast<char const *>(p);
+#endif
+        if (s == nullptr) {
+            SAL_DEBUG("nullptr");
+            std::abort();
+        }
+        if (!rtl_convertStringToUString(
+                &id.pData, s, len,
+                RTL_TEXTENCODING_UTF8,
+                (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+                 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+                 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+        {
+            SAL_DEBUG("not UTF-8");
+            std::abort();
+        }
+        g_variant_unref(v);
+        g_variant_unref(ret);
+    }
+    g_object_unref(proxy);
+    SAL_DEBUG("CHOSE "<<int(!cncl)<<" <"<<id<<">");
+    if (cncl) {
+        return RET_CANCEL;
+    } else {
+#if 0
+        URL_ = "document:" + id;
+#else
+        URL_ = "file://" + id;
+#endif
+        return RET_OK;
+    }
 }
 
 
@@ -588,6 +632,10 @@ OUString SAL_CALL SvtFilePicker::getDisplayDirectory() throw( RuntimeException,
 
 Sequence< OUString > SAL_CALL SvtFilePicker::getFiles() throw( RuntimeException, std::exception )
 {
+if(true) {
+    SAL_DEBUG("getFiles <"<<URL_<<">");
+    return {URL_};
+}
     checkAlive();
 
     SolarMutexGuard aGuard;
diff --git a/fpicker/source/office/OfficeFilePicker.hxx b/fpicker/source/office/OfficeFilePicker.hxx
index fa8313e..685e40c 100644
--- a/fpicker/source/office/OfficeFilePicker.hxx
+++ b/fpicker/source/office/OfficeFilePicker.hxx
@@ -19,7 +19,7 @@
 #ifndef INCLUDED_FPICKER_SOURCE_OFFICE_OFFICEFILEPICKER_HXX
 #define INCLUDED_FPICKER_SOURCE_OFFICE_OFFICEFILEPICKER_HXX
 
-#include <cppuhelper/implbase5.hxx>
+#include <cppuhelper/implbase4.hxx>
 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
 #include <com/sun/star/ui/dialogs/XFilePreview.hpp>
 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
@@ -50,11 +50,10 @@ typedef ::com::sun::star::uno::Sequence< OUString >  OUStringList;   // can be t
 
 // class SvtFilePicker ---------------------------------------------------
 
-typedef ::cppu::ImplHelper5 <   ::com::sun::star::ui::dialogs::XFilePicker3
+typedef ::cppu::ImplHelper4 <   ::com::sun::star::ui::dialogs::XFilePicker3
                             ,   ::com::sun::star::ui::dialogs::XFilePickerControlAccess
                             ,   ::com::sun::star::ui::dialogs::XFilePreview
                             ,   ::com::sun::star::lang::XServiceInfo
-                            ,   ::com::sun::star::ui::dialogs::XAsynchronousExecutableDialog
                             >   SvtFilePicker_Base;
 
 class SvtFilePicker :public SvtFilePicker_Base
@@ -103,14 +102,6 @@ public:
     virtual sal_Int16 SAL_CALL execute(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
 
 
-    // XAsynchronousExecutableDialog functions
-
-    virtual void SAL_CALL setDialogTitle( const OUString& _rTitle ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
-    virtual void SAL_CALL startExecuteModal( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener >& xListener )
-        throw (::com::sun::star::uno::RuntimeException,
-               std::exception) SAL_OVERRIDE;
-
-
     // XFilePicker functions
 
 
@@ -224,6 +215,8 @@ private:
     void                prepareExecute( );
 
     DECL_LINK(          DialogClosedHdl, Dialog* );
+
+    OUString URL_;
 };
 
 #endif // INCLUDED_FPICKER_SOURCE_OFFICE_OFFICEFILEPICKER_HXX

which on the one hand works around the xml-config problem I mention in the presentation and on the other hand hacks in some initial demo support for the document portal.

The latter works by replacing the LibreOffice-internal file picker (“Tools – Options… – LibreOffcie – General – Open/Save Dialogs – Use LibreOffice dialogs”) with the xdg-content-choser (you need the latest git revision of the chooser, along with the latest git revision of xdg-app for that to work). Once you select the LibreOffice-internal file picker, you can open a document from outside the sandbox, read-only for now. Read-write and saving back is next on the agenda…

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s