[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.1' - desktop/CppunitTest_desktop_app.mk desktop/Module_desktop.mk desktop/qa desktop/source

Mike Kaganski mike.kaganski at collabora.com
Fri Dec 16 10:15:19 UTC 2016


 desktop/CppunitTest_desktop_app.mk          |   28 +++++++
 desktop/Module_desktop.mk                   |    1 
 desktop/qa/desktop_app/test_desktop_app.cxx |  101 ++++++++++++++++++++++++++++
 desktop/source/app/cmdlineargs.cxx          |   84 +++++++++++++++++++++++
 desktop/source/app/cmdlineargs.hxx          |   13 +--
 5 files changed, 220 insertions(+), 7 deletions(-)

New commits:
commit 8c0743c21156d39384ffcb49fd92144eb22e71e8
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date:   Mon Jul 11 06:38:50 2016 +1000

    tdf#100837: Support Office URI Schemes
    
    This patch adds support for Office URI Schemes (see
    https://msdn.microsoft.com/en-us/library/dn906146).
    This will enable browser (non-CMIS) integration of LibreOffice
    with MS SharePoint server (v.2013 tested).
    
    In this patch, in addition to ms-* schemes, a new scheme is
    introduced: vnd.libreoffice.command, which is analogous to ms-*.
    Its purpose is to enable flexible configuration of server and
    client, where some types of documents are declared as handled by
    LibreOffice, and other are handled by other software. E.g., ODTs
    may have "vnd.libreoffice.command" scheme, while DOCXs could be
    "ms-word". Client may register LibreOffice to handle both, or to
    handle only "vnd.libreoffice.command" scheme.
    
    Unit test included.
    
    TODO in a later patch: add a mechanism to register LibreOffice
    to the schemes with OS.
    
    Change-Id: I1c449a211102036f87163058a4c90a93eb32c948
    Reviewed-on: https://gerrit.libreoffice.org/27094
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/32007
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/desktop/CppunitTest_desktop_app.mk b/desktop/CppunitTest_desktop_app.mk
new file mode 100644
index 0000000..1275b6e
--- /dev/null
+++ b/desktop/CppunitTest_desktop_app.mk
@@ -0,0 +1,28 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,desktop_app))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,desktop_app, \
+    desktop/qa/desktop_app/test_desktop_app \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,desktop_app, \
+    comphelper \
+    cppu \
+    cppuhelper \
+    sal \
+    sofficeapp \
+))
+
+$(eval $(call gb_CppunitTest_use_external,desktop_app,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,desktop_app))
+
+# vim: set noet sw=4 ts=4:
diff --git a/desktop/Module_desktop.mk b/desktop/Module_desktop.mk
index d74d406..50ec774 100644
--- a/desktop/Module_desktop.mk
+++ b/desktop/Module_desktop.mk
@@ -127,6 +127,7 @@ $(eval $(call gb_Module_add_targets,desktop, \
 endif
 
 $(eval $(call gb_Module_add_check_targets,desktop, \
+    CppunitTest_desktop_app \
     CppunitTest_desktop_version \
 ))
 
diff --git a/desktop/qa/desktop_app/test_desktop_app.cxx b/desktop/qa/desktop_app/test_desktop_app.cxx
new file mode 100644
index 0000000..c800b2c
--- /dev/null
+++ b/desktop/qa/desktop_app/test_desktop_app.cxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cstddef>
+#include <sal/types.h>
+
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "cppunit/plugin/TestPlugIn.h"
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+
+#include "../../source/app/cmdlineargs.hxx"
+
+namespace {
+
+class Test: public ::CppUnit::TestFixture {
+public:
+    void testTdf100837();
+
+    CPPUNIT_TEST_SUITE(Test);
+    CPPUNIT_TEST(testTdf100837);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+class TestSupplier : public desktop::CommandLineArgs::Supplier {
+public:
+    virtual ~TestSupplier() {}
+    virtual boost::optional< OUString > getCwdUrl() override { return boost::optional< OUString >(); }
+    virtual bool next(OUString * argument) override {
+        CPPUNIT_ASSERT(argument != nullptr);
+        if (m_index < m_args.size()) {
+            *argument = m_args[m_index++];
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+    TestSupplier& operator << (const OUString& arg) { m_args.push_back(arg); return *this; }
+private:
+    std::vector< OUString > m_args;
+    std::vector< OUString >::size_type m_index = 0;
+};
+
+// Test Office URI Schemes support
+void Test::testTdf100837() {
+    auto xContext = ::cppu::defaultBootstrap_InitialComponentContext();
+    ::css::uno::Reference<::css::lang::XMultiComponentFactory> xFactory(xContext->getServiceManager());
+    ::css::uno::Reference<::css::lang::XMultiServiceFactory> xSM(xFactory, ::css::uno::UNO_QUERY_THROW);
+    // Without this we're crashing because callees are using getProcessServiceFactory
+    ::comphelper::setProcessServiceFactory(xSM);
+
+    TestSupplier supplier;
+    supplier << "--view" << "foo" << "ms-word:ofe|u|bar1" << "ms-word:ofv|u|bar2" << "ms-word:nft|u|bar3" << "baz";
+    desktop::CommandLineArgs args(supplier);
+    auto vViewList = args.GetViewList();
+    auto vForceOpenList = args.GetForceOpenList();
+    auto vForceNewList = args.GetForceNewList();
+    // 3 documents go to View list: foo; bar2; baz
+    CPPUNIT_ASSERT_EQUAL(decltype(vViewList.size())(3), vViewList.size());
+    CPPUNIT_ASSERT_EQUAL(OUString("foo"),  vViewList[0]);
+    CPPUNIT_ASSERT_EQUAL(OUString("bar2"), vViewList[1]);
+    CPPUNIT_ASSERT_EQUAL(OUString("baz"),  vViewList[2]);
+    // 1 document goes to ForceOpen list: bar1
+    CPPUNIT_ASSERT_EQUAL(decltype(vForceOpenList.size())(1), vForceOpenList.size());
+    CPPUNIT_ASSERT_EQUAL(OUString("bar1"), vForceOpenList[0]);
+    // 1 document goes to ForceNew list: bar3
+    CPPUNIT_ASSERT_EQUAL(decltype(vForceNewList.size())(1), vForceNewList.size());
+    CPPUNIT_ASSERT_EQUAL(OUString("bar3"), vForceNewList[0]);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx
index aa65234..3f6a017 100644
--- a/desktop/source/app/cmdlineargs.cxx
+++ b/desktop/source/app/cmdlineargs.cxx
@@ -99,6 +99,80 @@ private:
     sal_uInt32 m_index;
 };
 
+// Office URI Schemes : see https://msdn.microsoft.com/en-us/library/dn906146
+class OfficeURISchemeCommandLineSupplier : public CommandLineArgs::Supplier {
+public:
+    static bool IsOfficeURI(const OUString& URI, OUString* rest = nullptr)
+    {
+        return ( URI.startsWithIgnoreAsciiCase("vnd.libreoffice.command:", rest) // Proposed extended schema
+              || URI.startsWithIgnoreAsciiCase("ms-word:",                 rest)
+              || URI.startsWithIgnoreAsciiCase("ms-powerpoint:",           rest)
+              || URI.startsWithIgnoreAsciiCase("ms-excel:",                rest)
+              || URI.startsWithIgnoreAsciiCase("ms-visio:",                rest)
+              || URI.startsWithIgnoreAsciiCase("ms-access:",               rest));
+    }
+    OfficeURISchemeCommandLineSupplier(boost::optional< OUString > cwdUrl, const OUString& URI)
+        : m_cwdUrl(cwdUrl)
+    {
+        // 1. Strip the scheme name
+        OUString rest1;
+        bool isOfficeURI = IsOfficeURI(URI, &rest1);
+        assert(isOfficeURI);
+        (void) isOfficeURI;
+
+        OUString rest2;
+        long nURIlen = -1;
+        // 2. Discriminate by command name (incl. 1st command argument descriptor)
+        //    Extract URI: everything up to possible next argument
+        if (rest1.startsWith("ofv|u|", &rest2))
+        {
+            // Open for view
+            m_args.push_back("--view");
+            nURIlen = rest2.indexOf("|");
+        }
+        else if (rest1.startsWith("ofe|u|", &rest2))
+        {
+            // Open for editing
+            m_args.push_back("-o");
+            nURIlen = rest2.indexOf("|");
+        }
+        else if (rest1.startsWith("nft|u|", &rest2))
+        {
+            // New from template
+            m_args.push_back("-n");
+            nURIlen = rest2.indexOf("|");
+            // TODO: process optional second argument (default save-to location)
+            // For now, we just ignore it
+        }
+        else
+        {
+            // Abbreviated schema: <scheme-name>:URI
+            // "ofv|u|" implied
+            rest2 = rest1;
+            m_args.push_back("--view");
+        }
+        if (nURIlen < 0)
+            nURIlen = rest2.getLength();
+        m_args.push_back(rest2.copy(0, nURIlen));
+    }
+    virtual ~OfficeURISchemeCommandLineSupplier() {}
+    virtual boost::optional< OUString > getCwdUrl() override { return m_cwdUrl; }
+    virtual bool next(OUString * argument) override {
+        assert(argument != nullptr);
+        if (m_index < m_args.size()) {
+            *argument = m_args[m_index++];
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+private:
+    boost::optional< OUString > m_cwdUrl;
+    std::vector< OUString > m_args;
+    std::vector< OUString >::size_type m_index = 0;
+};
+
 }
 
 CommandLineArgs::Supplier::Exception::Exception() {}
@@ -534,7 +608,15 @@ void CommandLineArgs::ParseCommandLine_Impl( Supplier& supplier )
                 else
                 {
                     // handle this argument as a filename
-                    if ( bOpenEvent )
+
+                    // 1. Check if this is an Office URI
+                    if (!bDisplaySpec && OfficeURISchemeCommandLineSupplier::IsOfficeURI(aArg))
+                    {
+                        OfficeURISchemeCommandLineSupplier OfficeURISupplier(getCwdUrl(), aArg);
+                        // Add the file according its command, ignore current event
+                        ParseCommandLine_Impl(OfficeURISupplier);
+                    }
+                    else if ( bOpenEvent )
                     {
                         m_openlist.push_back(aArg);
                         bOpenDoc = true;
diff --git a/desktop/source/app/cmdlineargs.hxx b/desktop/source/app/cmdlineargs.hxx
index e0c3726..8e3863a 100644
--- a/desktop/source/app/cmdlineargs.hxx
+++ b/desktop/source/app/cmdlineargs.hxx
@@ -27,6 +27,7 @@
 #include <rtl/ustring.hxx>
 #include <boost/noncopyable.hpp>
 #include <boost/optional.hpp>
+#include <desktop/dllapi.h>
 
 namespace desktop
 {
@@ -34,7 +35,7 @@ namespace desktop
 class CommandLineArgs: private boost::noncopyable
 {
     public:
-        struct Supplier
+        struct DESKTOP_DLLPUBLIC Supplier
         {
             // Thrown from constructors and next:
             class Exception {
@@ -51,7 +52,7 @@ class CommandLineArgs: private boost::noncopyable
         };
 
         CommandLineArgs();
-        explicit CommandLineArgs( Supplier& supplier );
+        DESKTOP_DLLPUBLIC explicit CommandLineArgs( Supplier& supplier );
 
         boost::optional< OUString > getCwdUrl() const { return m_cwdUrl; }
 
@@ -97,11 +98,11 @@ class CommandLineArgs: private boost::noncopyable
         bool                    HasSplashPipe() const { return m_splashpipe;}
         std::vector< OUString > const & GetAccept() const { return m_accept;}
         std::vector< OUString > const & GetUnaccept() const { return m_unaccept;}
-        std::vector< OUString > GetOpenList() const;
-        std::vector< OUString > GetViewList() const;
+        DESKTOP_DLLPUBLIC std::vector< OUString > GetOpenList() const;
+        DESKTOP_DLLPUBLIC std::vector< OUString > GetViewList() const;
         std::vector< OUString > GetStartList() const;
-        std::vector< OUString > GetForceOpenList() const;
-        std::vector< OUString > GetForceNewList() const;
+        DESKTOP_DLLPUBLIC std::vector< OUString > GetForceOpenList() const;
+        DESKTOP_DLLPUBLIC std::vector< OUString > GetForceNewList() const;
         std::vector< OUString > GetPrintList() const;
         std::vector< OUString > GetPrintToList() const;
         OUString       GetPrinterName() const { return m_printername;}


More information about the Libreoffice-commits mailing list