summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2016-07-28 21:41:11 +1000
committerMike Kaganski <mike.kaganski@collabora.com>2016-07-31 09:34:59 +0000
commit4311e8fb88c334cccad6f577610e1af8ae75bc59 (patch)
tree1b702b5d3e2aafea363d417c1c0ebfa3321dc40a
parent59f5436f60a0201c8aa6a2415625b71134022af9 (diff)
tdf#100837: honor LibreOffice command line arguments for Office URIs
This patch allows modifying open mode set in Office URI by using LibreOffice usual command line arguments. For instance, if there is -p "ofe:...", then the file won't be open for editing, but instead will be printed. Change-Id: I4bde9b6e1c0e92b63ee3834ee1fd8f6e1bd321f2 Reviewed-on: https://gerrit.libreoffice.org/27629 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--desktop/qa/desktop_app/test_desktop_app.cxx56
-rw-r--r--desktop/source/app/cmdlineargs.cxx147
2 files changed, 105 insertions, 98 deletions
diff --git a/desktop/qa/desktop_app/test_desktop_app.cxx b/desktop/qa/desktop_app/test_desktop_app.cxx
index c800b2c1486a..9d8225e05812 100644
--- a/desktop/qa/desktop_app/test_desktop_app.cxx
+++ b/desktop/qa/desktop_app/test_desktop_app.cxx
@@ -47,6 +47,7 @@ public:
class TestSupplier : public desktop::CommandLineArgs::Supplier {
public:
+ TestSupplier(std::initializer_list<OUString> args) : m_args(args) {}
virtual ~TestSupplier() {}
virtual boost::optional< OUString > getCwdUrl() override { return boost::optional< OUString >(); }
virtual bool next(OUString * argument) override {
@@ -59,7 +60,6 @@ public:
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;
@@ -73,23 +73,43 @@ void Test::testTdf100837() {
// 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]);
+ {
+ // 1. Test default behaviour: Office URIs define open mode
+ TestSupplier supplier{ "foo", "ms-word:ofe|u|bar1", "ms-word:ofv|u|bar2", "ms-word:nft|u|bar3", "baz" };
+ desktop::CommandLineArgs args(supplier);
+ auto vOpenList = args.GetOpenList();
+ auto vForceOpenList = args.GetForceOpenList();
+ auto vViewList = args.GetViewList();
+ auto vForceNewList = args.GetForceNewList();
+ // 2 documents go to Open list: foo; baz
+ CPPUNIT_ASSERT_EQUAL(decltype(vOpenList.size())(2), vOpenList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("foo"), vOpenList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("baz"), vOpenList[1]);
+ // 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 View list: bar2
+ CPPUNIT_ASSERT_EQUAL(decltype(vViewList.size())(1), vViewList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar2"), vViewList[0]);
+ // 1 document goes to ForceNew list: bar3
+ CPPUNIT_ASSERT_EQUAL(decltype(vForceNewList.size())(1), vForceNewList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar3"), vForceNewList[0]);
+ }
+
+ {
+ // 2. Test explicit open mode arguments. Office URI commands should have no effect
+ TestSupplier supplier{ "--view", "ms-word:ofe|u|foo", "-o", "ms-word:ofv|u|bar", "ms-word:nft|u|baz" };
+ desktop::CommandLineArgs args(supplier);
+ auto vViewList = args.GetViewList();
+ auto vForceOpenList = args.GetForceOpenList();
+ // 1 document goes to View list: foo
+ CPPUNIT_ASSERT_EQUAL(decltype(vViewList.size())(1), vViewList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("foo"), vViewList[0]);
+ // 2 documents go to ForceOpen list: bar, baz
+ CPPUNIT_ASSERT_EQUAL(decltype(vForceOpenList.size())(2), vForceOpenList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar"), vForceOpenList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("baz"), vForceOpenList[1]);
+ }
}
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx
index f13e01c7b82d..f9a275876d2f 100644
--- a/desktop/source/app/cmdlineargs.cxx
+++ b/desktop/source/app/cmdlineargs.cxx
@@ -102,82 +102,74 @@ 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)
+enum class CommandLineEvent {
+ Open, Print, View, Start, PrintTo,
+ ForceOpen, ForceNew, Conversion, BatchPrint
+};
+
+// Office URI Schemes: see https://msdn.microsoft.com/en-us/library/dn906146
+// This functions checks if the arg is an Office URI.
+// If applicable, it updates arg to inner URI.
+// If no event argument is explicitly set in command line,
+// then it returns updated command line event,
+// according to Office URI command.
+CommandLineEvent CheckOfficeURI(/* in,out */ OUString& arg, CommandLineEvent curEvt)
+{
+ // 1. Strip the scheme name
+ OUString rest1;
+ bool isOfficeURI = ( arg.startsWithIgnoreAsciiCase("vnd.libreoffice.command:", &rest1) // Proposed extended schema
+ || arg.startsWithIgnoreAsciiCase("ms-word:", &rest1)
+ || arg.startsWithIgnoreAsciiCase("ms-powerpoint:", &rest1)
+ || arg.startsWithIgnoreAsciiCase("ms-excel:", &rest1)
+ || arg.startsWithIgnoreAsciiCase("ms-visio:", &rest1)
+ || arg.startsWithIgnoreAsciiCase("ms-access:", &rest1));
+ if (!isOfficeURI)
+ return curEvt;
+
+ 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))
{
- 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));
+ // Open for view - override only in default mode
+ if (curEvt == CommandLineEvent::Open)
+ curEvt = CommandLineEvent::View;
+ nURIlen = rest2.indexOf("|");
}
- OfficeURISchemeCommandLineSupplier(boost::optional< OUString > cwdUrl, const OUString& URI)
- : m_cwdUrl(cwdUrl)
+ else if (rest1.startsWith("ofe|u|", &rest2))
{
- // 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));
+ // Open for editing - override only in default mode
+ if (curEvt == CommandLineEvent::Open)
+ curEvt = CommandLineEvent::ForceOpen;
+ nURIlen = rest2.indexOf("|");
}
- 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;
- }
+ else if (rest1.startsWith("nft|u|", &rest2))
+ {
+ // New from template - override only in default mode
+ if (curEvt == CommandLineEvent::Open)
+ curEvt = CommandLineEvent::ForceNew;
+ nURIlen = rest2.indexOf("|");
+ // TODO: process optional second argument (default save-to location)
+ // For now, we just ignore it
}
-private:
- boost::optional< OUString > m_cwdUrl;
- std::vector< OUString > m_args;
- std::vector< OUString >::size_type m_index = 0;
-};
-
+ else
+ {
+ // Abbreviated scheme: <scheme-name>:URI
+ // "ofv|u|" implied
+ // override only in default mode
+ if (curEvt == CommandLineEvent::Open)
+ curEvt = CommandLineEvent::View;
+ rest2 = rest1;
+ }
+ if (nURIlen < 0)
+ nURIlen = rest2.getLength();
+ arg = rest2.copy(0, nURIlen);
+ return curEvt;
}
+} // namespace
+
CommandLineArgs::Supplier::Exception::Exception() {}
CommandLineArgs::Supplier::Exception::Exception(Exception const &) {}
@@ -207,9 +199,6 @@ CommandLineArgs::CommandLineArgs( Supplier& supplier )
void CommandLineArgs::ParseCommandLine_Impl( Supplier& supplier )
{
m_cwdUrl = supplier.getCwdUrl();
-
- enum class CommandLineEvent { Open, Print, View, Start, PrintTo,
- ForceOpen, ForceNew, Conversion, BatchPrint };
CommandLineEvent eCurrentEvent = CommandLineEvent::Open;
for (;;)
@@ -534,14 +523,12 @@ void CommandLineArgs::ParseCommandLine_Impl( Supplier& supplier )
{
// handle this argument as a filename
- // 1. Check if this is an Office URI
- if (OfficeURISchemeCommandLineSupplier::IsOfficeURI(aArg))
- {
- OfficeURISchemeCommandLineSupplier OfficeURISupplier(getCwdUrl(), aArg);
- // Add the file according its command, ignore current event
- ParseCommandLine_Impl(OfficeURISupplier);
- }
- else switch (eCurrentEvent)
+ // First check if this is an Office URI
+ // This will possibly adjust event for this argument
+ // and put real URI to aArg
+ CommandLineEvent eThisEvent = CheckOfficeURI(aArg, eCurrentEvent);
+
+ switch (eThisEvent)
{
case CommandLineEvent::Open:
m_openlist.push_back(aArg);