summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@collabora.com>2020-06-03 19:46:42 +0300
committerMert Tumer <mert.tumer@collabora.com>2020-09-28 11:53:16 +0200
commit4ad8773821f73fa0df665f4d2d4682237a7af677 (patch)
tree3ac0bcc358fdb427b00f2413dbc63272f69d5b4d
parent2b546f72dec43d8ac3bc24c1f767ceb7f617d9be (diff)
Make various bits of the UI configurable.
This adds the infrastructure to be able to pass the info which elements like the statusbar / ruler / sidebar are supposed to be shown or hidden on startup of the editor. Change-Id: I188264dec6961074444934ff5fd7088e23b170d4 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/103169 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Mert Tumer <mert.tumer@collabora.com>
-rw-r--r--Makefile.am1
-rw-r--r--loleaflet/html/loleaflet.html.m46
-rw-r--r--test/Makefile.am1
-rw-r--r--test/WhiteBoxTests.cpp15
-rw-r--r--wsd/FileServer.cpp3
-rw-r--r--wsd/FileServer.hpp8
-rw-r--r--wsd/FileServerUtil.cpp104
-rw-r--r--wsd/reference.md21
8 files changed, 157 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index e50b68022..1ab2f733b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -118,6 +118,7 @@ loolwsd_sources = common/Crypto.cpp \
wsd/LOOLWSD.cpp \
wsd/ClientSession.cpp \
wsd/FileServer.cpp \
+ wsd/FileServerUtil.cpp \
wsd/RequestDetails.cpp \
wsd/Storage.cpp \
wsd/TileCache.cpp \
diff --git a/loleaflet/html/loleaflet.html.m4 b/loleaflet/html/loleaflet.html.m4
index 7abe51f18..d180165e7 100644
--- a/loleaflet/html/loleaflet.html.m4
+++ b/loleaflet/html/loleaflet.html.m4
@@ -260,7 +260,8 @@ m4_ifelse(MOBILEAPP,[true],
window.protocolDebug = false;
window.frameAncestors = '';
window.socketProxy = false;
- window.tileSize = 256;],
+ window.tileSize = 256;
+ window.uiDefaults = {};],
[window.host = '%HOST%';
window.serviceRoot = '%SERVICE_ROOT%';
window.versionPath = '%VERSION%';
@@ -277,7 +278,8 @@ m4_ifelse(MOBILEAPP,[true],
window.protocolDebug = %PROTOCOL_DEBUG%;
window.frameAncestors = '%FRAME_ANCESTORS%';
window.socketProxy = %SOCKET_PROXY%;
- window.tileSize = 256;])
+ window.tileSize = 256;
+ window.uiDefaults = %UI_DEFAULTS%;])
m4_syscmd([cat ]GLOBAL_JS)m4_dnl
// Dynamically load the appropriate *-mobile.css, *-tablet.css or *-desktop.css
diff --git a/test/Makefile.am b/test/Makefile.am
index 967143b3e..1b1bcb28a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -67,6 +67,7 @@ wsd_sources = \
../common/Authorization.cpp \
../kit/Kit.cpp \
../kit/TestStubs.cpp \
+ ../wsd/FileServerUtil.cpp \
../wsd/RequestDetails.cpp \
../wsd/TileCache.cpp \
../wsd/ProofKey.cpp
diff --git a/test/WhiteBoxTests.cpp b/test/WhiteBoxTests.cpp
index 445a7134a..8f53c32ef 100644
--- a/test/WhiteBoxTests.cpp
+++ b/test/WhiteBoxTests.cpp
@@ -23,6 +23,7 @@
#include <RequestDetails.hpp>
#include <common/Authorization.hpp>
+#include <wsd/FileServer.hpp>
/// WhiteBox unit-tests.
class WhiteBoxTests : public CPPUNIT_NS::TestFixture
@@ -48,6 +49,7 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture
CPPUNIT_TEST(testRequestDetails_loleafletURI);
CPPUNIT_TEST(testRequestDetails_local);
CPPUNIT_TEST(testRequestDetails);
+ CPPUNIT_TEST(testUIDefaults);
CPPUNIT_TEST_SUITE_END();
@@ -70,6 +72,7 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture
void testRequestDetails_loleafletURI();
void testRequestDetails_local();
void testRequestDetails();
+ void testUIDefaults();
};
void WhiteBoxTests::testLOOLProtocolFunctions()
@@ -1563,6 +1566,18 @@ void WhiteBoxTests::testRequestDetails()
}
}
+void WhiteBoxTests::testUIDefaults()
+{
+ LOK_ASSERT_EQUAL(std::string("{\"uiMode\":\"classic\"}"),
+ FileServerRequestHandler::uiDefaultsToJSON("UIMode=classic;huh=bleh;"));
+
+ LOK_ASSERT_EQUAL(std::string("{\"spreadsheet\":{\"ShowSidebar\":false},\"text\":{\"ShowRuler\":true}}"),
+ FileServerRequestHandler::uiDefaultsToJSON("TextRuler=true;SpreadsheetSidebar=false"));
+
+ LOK_ASSERT_EQUAL(std::string("{\"presentation\":{\"ShowStatusbar\":false},\"spreadsheet\":{\"ShowSidebar\":false},\"text\":{\"ShowRuler\":true},\"uiMode\":\"notebookbar\"}"),
+ FileServerRequestHandler::uiDefaultsToJSON(";;UIMode=notebookbar;;PresentationStatusbar=false;;TextRuler=true;;bah=ugh;;SpreadsheetSidebar=false"));
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(WhiteBoxTests);
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp
index fcf853173..56ff49801 100644
--- a/wsd/FileServer.cpp
+++ b/wsd/FileServer.cpp
@@ -677,6 +677,8 @@ void FileServerRequestHandler::preprocessFile(const HTTPRequest& request,
LOG_TRC("access_token=" << accessToken << ", access_token_ttl=" << accessTokenTtl);
const std::string accessHeader = form.get("access_header", "");
LOG_TRC("access_header=" << accessHeader);
+ const std::string uiDefaults = form.get("ui_defaults", "");
+ LOG_TRC("ui_defaults=" << uiDefaults);
// Escape bad characters in access token.
// This is placed directly in javascript in loleaflet.html, we need to make sure
@@ -718,6 +720,7 @@ void FileServerRequestHandler::preprocessFile(const HTTPRequest& request,
Poco::replaceInPlace(preprocess, std::string("%HOST%"), cnxDetails.getWebSocketUrl());
Poco::replaceInPlace(preprocess, std::string("%VERSION%"), std::string(LOOLWSD_VERSION_HASH));
Poco::replaceInPlace(preprocess, std::string("%SERVICE_ROOT%"), responseRoot);
+ Poco::replaceInPlace(preprocess, std::string("%UI_DEFAULTS%"), uiDefaultsToJSON(uiDefaults));
const auto& config = Application::instance().config();
std::string protocolDebug = "false";
diff --git a/wsd/FileServer.hpp b/wsd/FileServer.hpp
index 58cbb0b28..1cad001fb 100644
--- a/wsd/FileServer.hpp
+++ b/wsd/FileServer.hpp
@@ -18,6 +18,8 @@ class RequestDetails;
/// Handles file requests over HTTP(S).
class FileServerRequestHandler
{
+ friend class WhiteBoxTests; // for unit testing
+
static std::string getRequestPathname(const Poco::Net::HTTPRequest& request);
static void preprocessFile(const Poco::Net::HTTPRequest& request,
@@ -27,6 +29,12 @@ class FileServerRequestHandler
static void preprocessAdminFile(const Poco::Net::HTTPRequest& request,
const RequestDetails &requestDetails,
const std::shared_ptr<StreamSocket>& socket);
+
+ /// Construct a JSON to be accepted by the loleflet.html from a list like
+ /// UIMode=classic;TextRuler=true;PresentationStatusbar=false
+ /// that is passed as "ui_defaults" hidden input during the iframe setup.
+ static std::string uiDefaultsToJSON(const std::string& uiDefaults);
+
public:
/// Evaluate if the cookie exists, and if not, ask for the credentials.
static bool isAdminLoggedIn(const Poco::Net::HTTPRequest& request, Poco::Net::HTTPResponse& response);
diff --git a/wsd/FileServerUtil.cpp b/wsd/FileServerUtil.cpp
new file mode 100644
index 000000000..dbbc90028
--- /dev/null
+++ b/wsd/FileServerUtil.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/.
+ */
+
+#include <config.h>
+
+#include <Poco/JSON/Object.h>
+
+#include "FileServer.hpp"
+
+std::string FileServerRequestHandler::uiDefaultsToJSON(const std::string& uiDefaults)
+{
+ static std::string previousUIDefaults;
+ static std::string previousJSON("{}");
+
+ // early exit if we are serving the same thing
+ if (uiDefaults == previousUIDefaults)
+ return previousJSON;
+
+ Poco::JSON::Object json;
+ Poco::JSON::Object textDefs;
+ Poco::JSON::Object spreadsheetDefs;
+ Poco::JSON::Object presentationDefs;
+
+ StringVector tokens(Util::tokenize(uiDefaults, ';'));
+ for (const auto& token : tokens)
+ {
+ StringVector keyValue(Util::tokenize(tokens.getParam(token), '='));
+ Poco::JSON::Object* currentDef = nullptr;
+ std::string key;
+
+ // detect the UIMode or component
+ if (keyValue[0] == "UIMode")
+ {
+ if (keyValue[1] == "classic" || keyValue[1] == "notebookbar")
+ json.set("uiMode", keyValue[1]);
+ else
+ LOG_WRN("unknown UIMode value " << keyValue[1]);
+
+ continue;
+ }
+ else if (Util::startsWith(keyValue[0], "Text"))
+ {
+ currentDef = &textDefs;
+ key = keyValue[0].substr(4);
+ }
+ else if (Util::startsWith(keyValue[0], "Spreadsheet"))
+ {
+ currentDef = &spreadsheetDefs;
+ key = keyValue[0].substr(11);
+ }
+ else if (Util::startsWith(keyValue[0], "Presentation"))
+ {
+ currentDef = &presentationDefs;
+ key = keyValue[0].substr(12);
+ }
+ else
+ {
+ LOG_WRN("unknown UI default's component " << keyValue[0]);
+ continue;
+ }
+
+ assert(currentDef);
+
+ // detect the actual UI widget we want to hide or show
+ if (key == "Ruler" || key == "Sidebar" || key == "Statusbar")
+ {
+ bool value(true);
+ if (keyValue[1] == "false" || keyValue[1] == "False" || keyValue[1] == "0")
+ value = false;
+
+ currentDef->set("Show" + key, value);
+ }
+ else
+ {
+ LOG_WRN("unknown UI default " << keyValue[0]);
+ continue;
+ }
+ }
+
+ if (textDefs.size() > 0)
+ json.set("text", textDefs);
+
+ if (spreadsheetDefs.size() > 0)
+ json.set("spreadsheet", spreadsheetDefs);
+
+ if (presentationDefs.size() > 0)
+ json.set("presentation", presentationDefs);
+
+ std::ostringstream oss;
+ Poco::JSON::Stringifier::stringify(json, oss);
+
+ previousUIDefaults = uiDefaults;
+ previousJSON = oss.str();
+
+ return previousJSON;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/wsd/reference.md b/wsd/reference.md
index e8798debc..0c987f9eb 100644
--- a/wsd/reference.md
+++ b/wsd/reference.md
@@ -128,6 +128,27 @@ PostMessage extensions
### App_LoadingStatus
Was extended with field 'Status' with 'Document_Loaded' value when document was loaded successfully and 'Failed' in other case.
+User Interface modifications
+----------------------------
+
+Some parts of the user interface can be hidden or shown based or what the
+integration needs. This is controlled by:
+
+ <input name="ui_defaults" value="VALUES" type="hidden"/>'
+
+during sending the form when the iframe is being set up (similarly as the
+access_token). The VALUES can have a form like:
+
+ UIMode=notebookbar;TextRuler=false;PresentationStatusbar=false;SpreadsheetSidebar=false
+
+where the:
+
+* UIMode specifies the general mode of operatior (classic or notebookbar)
+
+* Text, Presentation or Spreadsheet - are prefixes to identify the component
+
+* Ruler, Statusbar, Sidebar - are the UI parts that can be affected by this.
+
Alternative authentication possibility
--------------------------------------