[Libreoffice-commits] online.git: 2 commits - loolwsd/bundled loolwsd/ChildSession.cpp loolwsd/ChildSession.hpp loolwsd/LibreOfficeKit.hpp loolwsd/LOOLKit.cpp loolwsd/Makefile.am loolwsd/test

Jan Holesovsky kendy at collabora.com
Tue Nov 15 12:13:47 UTC 2016


 loolwsd/ChildSession.cpp                                  |  152 +--
 loolwsd/ChildSession.hpp                                  |   30 
 loolwsd/LOOLKit.cpp                                       |   72 -
 loolwsd/LibreOfficeKit.hpp                                |  646 --------------
 loolwsd/Makefile.am                                       |    1 
 loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h   |    1 
 loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.hxx |  610 +++++++++++++
 loolwsd/test/WhiteBoxTests.cpp                            |   28 
 8 files changed, 773 insertions(+), 767 deletions(-)

New commits:
commit 72a5f35f30d2e9250795abf910a1456d7b62b78e
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Nov 15 12:50:58 2016 +0100

    LibreOfficeKit.hpp changed meaning of getPart(), update accordingly.
    
    Change-Id: Ia346f4f838856040fa9aea26b3ac9c0b596b9218

diff --git a/loolwsd/ChildSession.cpp b/loolwsd/ChildSession.cpp
index ecd98c9..07b3a4c 100644
--- a/loolwsd/ChildSession.cpp
+++ b/loolwsd/ChildSession.cpp
@@ -100,7 +100,9 @@ bool ChildSession::_handleInput(const char *buffer, int length)
         std::vector<int> viewIds(viewCount);
         getLOKitDocument()->getViewIds(viewIds.data(), viewCount);
 
-        const int curPart = getLOKitDocument()->getPart();
+        int curPart = 0;
+        if (getLOKitDocument()->getDocumentType() != LOK_DOCTYPE_TEXT)
+            curPart = getLOKitDocument()->getPart();
 
         lockLokDoc.unlock();
 
@@ -919,7 +921,7 @@ bool ChildSession::setClientPart(const char* /*buffer*/, int /*length*/, StringT
 
     getLOKitDocument()->setView(_viewId);
 
-    if (part != getLOKitDocument()->getPart())
+    if (getLOKitDocument()->getDocumentType() != LOK_DOCTYPE_TEXT && part != getLOKitDocument()->getPart())
     {
         getLOKitDocument()->setPart(part);
     }
commit 2069650ba64bf9bbb8a4b8f28add7502e1d24dc5
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Nov 15 11:37:47 2016 +0100

    Get rid of LibreOfficeKit.hpp, it's mostly a copy of LibreOfficeKit.hxx.
    
    Change-Id: I55f9c28a3ac1ef2a36c18c29cc16209bedd48770

diff --git a/loolwsd/ChildSession.cpp b/loolwsd/ChildSession.cpp
index c28cfbf..ecd98c9 100644
--- a/loolwsd/ChildSession.cpp
+++ b/loolwsd/ChildSession.cpp
@@ -83,7 +83,7 @@ bool ChildSession::_handleInput(const char *buffer, int length)
         updateLastActivityTime();
     }
 
-    if (tokens.count() > 0 && tokens[0] == "useractive" && _loKitDocument != nullptr)
+    if (tokens.count() > 0 && tokens[0] == "useractive" && getLOKitDocument() != nullptr)
     {
         LOG_DBG("Handling message after inactivity of " << getInactivityMS() << "ms.");
         setIsActive(true);
@@ -91,16 +91,16 @@ bool ChildSession::_handleInput(const char *buffer, int length)
         // Client is getting active again.
         // Send invalidation and other sync-up messages.
         std::unique_lock<std::recursive_mutex> lock(Mutex); //TODO: Move to top of function?
-        auto lockLokDoc(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lockLokDoc(_docManager.getDocumentMutex());
 
-        _loKitDocument->setView(_viewId);
+        getLOKitDocument()->setView(_viewId);
 
         // Get the list of view ids from the core
-        const int viewCount = _loKitDocument->getViewsCount();
+        const int viewCount = getLOKitDocument()->getViewsCount();
         std::vector<int> viewIds(viewCount);
-        _loKitDocument->getViewIds(viewIds.data(), viewCount);
+        getLOKitDocument()->getViewIds(viewIds.data(), viewCount);
 
-        const int curPart = _loKitDocument->getPart();
+        const int curPart = getLOKitDocument()->getPart();
 
         lockLokDoc.unlock();
 
@@ -311,8 +311,8 @@ bool ChildSession::loadDocument(const char * /*buffer*/, int /*length*/, StringT
 
     std::unique_lock<std::recursive_mutex> lock(Mutex);
 
-    _loKitDocument = _docManager.onLoad(getId(), _jailedFilePath, _userName, _docPassword, renderOpts, _haveDocPassword);
-    if (!_loKitDocument || _viewId < 0)
+    bool loaded = _docManager.onLoad(getId(), _jailedFilePath, _userName, _docPassword, renderOpts, _haveDocPassword);
+    if (!loaded || _viewId < 0)
     {
         LOG_ERR("Failed to get LoKitDocument instance.");
         return false;
@@ -321,19 +321,19 @@ bool ChildSession::loadDocument(const char * /*buffer*/, int /*length*/, StringT
     LOG_INF("Created new view with viewid: [" << _viewId << + "] for username: [" <<
             _userName << "] in session: [" << getId() << "].");
 
-    auto lockLokDoc(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lockLokDoc(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _docType = LOKitHelper::getDocumentTypeAsString(_loKitDocument->get());
+    _docType = LOKitHelper::getDocumentTypeAsString(getLOKitDocument()->get());
     if (_docType != "text" && part != -1)
     {
-        _loKitDocument->setPart(part);
+        getLOKitDocument()->setPart(part);
     }
 
     // Respond by the document status
     LOG_DBG("Sending status after loading view " << _viewId << ".");
-    const auto status = LOKitHelper::documentStatus(_loKitDocument->get());
+    const auto status = LOKitHelper::documentStatus(getLOKitDocument()->get());
     if (status.empty() || !sendTextFrame("status: " + status))
     {
         LOG_ERR("Failed to get/forward document status [" << status << "].");
@@ -341,9 +341,9 @@ bool ChildSession::loadDocument(const char * /*buffer*/, int /*length*/, StringT
     }
 
     // Get the list of view ids from the core
-    const int viewCount = _loKitDocument->getViewsCount();
+    const int viewCount = getLOKitDocument()->getViewsCount();
     std::vector<int> viewIds(viewCount);
-    _loKitDocument->getViewIds(viewIds.data(), viewCount);
+    getLOKitDocument()->getViewIds(viewIds.data(), viewCount);
 
     lockLokDoc.unlock();
 
@@ -379,11 +379,11 @@ bool ChildSession::sendFontRendering(const char* /*buffer*/, int /*length*/, Str
     unsigned char* ptrFont = nullptr;
 
     {
-        auto lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-        _loKitDocument->setView(_viewId);
+        getLOKitDocument()->setView(_viewId);
 
-        ptrFont = _loKitDocument->renderFont(decodedFont.c_str(), text.c_str(), &width, &height);
+        ptrFont = getLOKitDocument()->renderFont(decodedFont.c_str(), text.c_str(), &width, &height);
     }
 
     LOG_TRC("renderFont [" << font << "] rendered in " << (timestamp.elapsed()/1000.) << "ms");
@@ -403,11 +403,11 @@ bool ChildSession::getStatus(const char* /*buffer*/, int /*length*/)
 {
     std::string status;
     {
-        auto lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-        _loKitDocument->setView(_viewId);
+        getLOKitDocument()->setView(_viewId);
 
-        status = LOKitHelper::documentStatus(_loKitDocument->get());
+        status = LOKitHelper::documentStatus(getLOKitDocument()->get());
     }
 
     if (status.empty())
@@ -462,16 +462,16 @@ bool ChildSession::getCommandValues(const char* /*buffer*/, int /*length*/, Stri
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
     if (command == ".uno:DocumentRepair")
     {
         char* pUndo;
         const std::string jsonTemplate("{\"commandName\":\".uno:DocumentRepair\",\"Redo\":%s,\"Undo\":%s}");
-        pValues = _loKitDocument->getCommandValues(".uno:Redo");
-        pUndo = _loKitDocument->getCommandValues(".uno:Undo");
+        pValues = getLOKitDocument()->getCommandValues(".uno:Redo");
+        pUndo = getLOKitDocument()->getCommandValues(".uno:Undo");
         std::string json = Poco::format(jsonTemplate,
                                         std::string(pValues == nullptr ? "" : pValues),
                                         std::string(pUndo == nullptr ? "" : pUndo));
@@ -484,7 +484,7 @@ bool ChildSession::getCommandValues(const char* /*buffer*/, int /*length*/, Stri
     }
     else
     {
-        pValues = _loKitDocument->getCommandValues(command.c_str());
+        pValues = getLOKitDocument()->getCommandValues(command.c_str());
         success = sendTextFrame("commandvalues: " + std::string(pValues == nullptr ? "" : pValues));
         std::free(pValues);
     }
@@ -496,10 +496,10 @@ bool ChildSession::getPartPageRectangles(const char* /*buffer*/, int /*length*/)
 {
     char* partPage = nullptr;
     {
-        auto lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-        _loKitDocument->setView(_viewId);
-        partPage = _loKitDocument->getPartPageRectangles();
+        getLOKitDocument()->setView(_viewId);
+        partPage = getLOKitDocument()->getPartPageRectangles();
     }
 
     sendTextFrame("partpagerectangles: " + std::string(partPage));
@@ -521,11 +521,11 @@ bool ChildSession::clientZoom(const char* /*buffer*/, int /*length*/, StringToke
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->setClientZoom(tilePixelWidth, tilePixelHeight, tileTwipWidth, tileTwipHeight);
+    getLOKitDocument()->setClientZoom(tilePixelWidth, tilePixelHeight, tileTwipWidth, tileTwipHeight);
     return true;
 }
 
@@ -546,11 +546,11 @@ bool ChildSession::clientVisibleArea(const char* /*buffer*/, int /*length*/, Str
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->setClientVisibleArea(x, y, width, height);
+    getLOKitDocument()->setClientVisibleArea(x, y, width, height);
     return true;
 }
 
@@ -584,9 +584,9 @@ bool ChildSession::downloadAs(const char* /*buffer*/, int /*length*/, StringToke
     const auto url = JAILED_DOCUMENT_ROOT + tmpDir + "/" + filenameParam.getFileName();
 
     {
-        auto lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-        _loKitDocument->saveAs(url.c_str(),
+        getLOKitDocument()->saveAs(url.c_str(),
                 format.size() == 0 ? nullptr :format.c_str(),
                 filterOptions.size() == 0 ? nullptr : filterOptions.c_str());
     }
@@ -615,11 +615,11 @@ bool ChildSession::getTextSelection(const char* /*buffer*/, int /*length*/, Stri
 
     char* textSelection = nullptr;
     {
-        auto lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-        _loKitDocument->setView(_viewId);
+        getLOKitDocument()->setView(_viewId);
 
-        textSelection = _loKitDocument->getTextSelection(mimeType.c_str(), nullptr);
+        textSelection = getLOKitDocument()->getTextSelection(mimeType.c_str(), nullptr);
     }
 
     sendTextFrame("textselectioncontent: " + std::string(textSelection));
@@ -641,11 +641,11 @@ bool ChildSession::paste(const char* buffer, int length, StringTokenizer& tokens
     const char* data = buffer + firstLine.size() + 1;
     const size_t size = length - firstLine.size() - 1;
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->paste(mimeType.c_str(), data, size);
+    getLOKitDocument()->paste(mimeType.c_str(), data, size);
 
     return true;
 }
@@ -671,11 +671,11 @@ bool ChildSession::insertFile(const char* /*buffer*/, int /*length*/, StringToke
                 "\"value\":\"" + fileName + "\""
             "}}";
 
-        auto lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-        _loKitDocument->setView(_viewId);
+        getLOKitDocument()->setView(_viewId);
 
-        _loKitDocument->postUnoCommand(command.c_str(), arguments.c_str(), false);
+        getLOKitDocument()->postUnoCommand(command.c_str(), arguments.c_str(), false);
     }
 
     return true;
@@ -711,11 +711,11 @@ bool ChildSession::keyEvent(const char* /*buffer*/, int /*length*/, StringTokeni
         return true;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->postKeyEvent(type, charcode, keycode);
+    getLOKitDocument()->postKeyEvent(type, charcode, keycode);
 
     return true;
 }
@@ -756,11 +756,11 @@ bool ChildSession::mouseEvent(const char* /*buffer*/, int /*length*/, StringToke
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->postMouseEvent(type, x, y, count, buttons, modifier);
+    getLOKitDocument()->postMouseEvent(type, x, y, count, buttons, modifier);
 
     return true;
 }
@@ -776,9 +776,9 @@ bool ChildSession::unoCommand(const char* /*buffer*/, int /*length*/, StringToke
     // we need to get LOK_CALLBACK_UNO_COMMAND_RESULT callback when saving
     const bool bNotify = (tokens[1] == ".uno:Save");
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
     if (tokens.count() == 2 && tokens[1] == ".uno:fakeDiskFull")
     {
@@ -786,11 +786,11 @@ bool ChildSession::unoCommand(const char* /*buffer*/, int /*length*/, StringToke
     }
     else if (tokens.count() == 2)
     {
-        _loKitDocument->postUnoCommand(tokens[1].c_str(), nullptr, bNotify);
+        getLOKitDocument()->postUnoCommand(tokens[1].c_str(), nullptr, bNotify);
     }
     else
     {
-        _loKitDocument->postUnoCommand(tokens[1].c_str(),
+        getLOKitDocument()->postUnoCommand(tokens[1].c_str(),
                                        Poco::cat(std::string(" "), tokens.begin() + 2, tokens.end()).c_str(),
                                        bNotify);
     }
@@ -814,11 +814,11 @@ bool ChildSession::selectText(const char* /*buffer*/, int /*length*/, StringToke
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->setTextSelection(type, x, y);
+    getLOKitDocument()->setTextSelection(type, x, y);
 
     return true;
 }
@@ -838,11 +838,11 @@ bool ChildSession::selectGraphic(const char* /*buffer*/, int /*length*/, StringT
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->setGraphicSelection(type, x, y);
+    getLOKitDocument()->setGraphicSelection(type, x, y);
 
     return true;
 }
@@ -855,11 +855,11 @@ bool ChildSession::resetSelection(const char* /*buffer*/, int /*length*/, String
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->resetSelection();
+    getLOKitDocument()->resetSelection();
 
     return true;
 }
@@ -887,11 +887,11 @@ bool ChildSession::saveAs(const char* /*buffer*/, int /*length*/, StringTokenize
 
     bool success = false;
     {
-        auto lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-        _loKitDocument->setView(_viewId);
+        getLOKitDocument()->setView(_viewId);
 
-        success = _loKitDocument->saveAs(url.c_str(),
+        success = getLOKitDocument()->saveAs(url.c_str(),
                 format.size() == 0 ? nullptr :format.c_str(),
                 filterOptions.size() == 0 ? nullptr : filterOptions.c_str());
     }
@@ -915,13 +915,13 @@ bool ChildSession::setClientPart(const char* /*buffer*/, int /*length*/, StringT
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    if (part != _loKitDocument->getPart())
+    if (part != getLOKitDocument()->getPart())
     {
-        _loKitDocument->setPart(part);
+        getLOKitDocument()->setPart(part);
     }
 
     return true;
@@ -937,11 +937,11 @@ bool ChildSession::setPage(const char* /*buffer*/, int /*length*/, StringTokeniz
         return false;
     }
 
-    auto lock(_loKitDocument->getLock());
+    std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
-    _loKitDocument->setView(_viewId);
+    getLOKitDocument()->setView(_viewId);
 
-    _loKitDocument->setPart(page);
+    getLOKitDocument()->setPart(page);
     return true;
 }
 
diff --git a/loolwsd/ChildSession.hpp b/loolwsd/ChildSession.hpp
index 624090c..871de23 100644
--- a/loolwsd/ChildSession.hpp
+++ b/loolwsd/ChildSession.hpp
@@ -12,13 +12,15 @@
 
 #include <mutex>
 
+#define LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKit.hxx>
+
 #include <Poco/NotificationQueue.h>
 #include <Poco/Thread.h>
 
 #include "Common.hpp"
 #include "LOOLKit.hpp"
 #include "LOOLSession.hpp"
-#include "LibreOfficeKit.hpp"
 
 class ChildSession;
 
@@ -28,23 +30,31 @@ class IDocumentManager
 {
 public:
     /// Reqest loading a document, or a new view, if one exists.
-    virtual std::shared_ptr<lok::Document> onLoad(const std::string& sessionId,
-                                                  const std::string& jailedFilePath,
-                                                  const std::string& userName,
-                                                  const std::string& docPassword,
-                                                  const std::string& renderOpts,
-                                                  const bool haveDocPassword)
+    virtual bool onLoad(const std::string& sessionId,
+                        const std::string& jailedFilePath,
+                        const std::string& userName,
+                        const std::string& docPassword,
+                        const std::string& renderOpts,
+                        const bool haveDocPassword)
         = 0;
 
     /// Unload a client session, which unloads the document
     /// if it is the last and only.
     virtual void onUnload(const ChildSession& session) = 0;
 
+    /// Access to the document instance.
+    virtual std::shared_ptr<lok::Document> getLOKitDocument() = 0;
+
     /// Send updated view info to all active sessions
     virtual void notifyViewInfo(const std::vector<int>& viewIds) = 0;
     /// Get a view ID <-> UserInfo map.
     virtual std::map<int, UserInfo> getViewInfo() = 0;
     virtual std::mutex& getMutex() = 0;
+
+    /// Mutex guarding the document - so that we can lock operations like
+    /// setting a view followed by a tile render, etc.
+    virtual std::mutex& getDocumentMutex() = 0;
+
     virtual std::shared_ptr<TileQueue>& getTileQueue() = 0;
 
     virtual bool sendTextFrame(const std::string& message) = 0;
@@ -115,6 +125,11 @@ private:
     virtual void disconnect() override;
     virtual bool _handleInput(const char* buffer, int length) override;
 
+    std::shared_ptr<lok::Document> getLOKitDocument()
+    {
+        return _docManager.getLOKitDocument();
+    }
+
 private:
     const std::string _jailId;
     IDocumentManager& _docManager;
@@ -125,7 +140,6 @@ private:
     /// Whether document has been opened succesfuly
     bool _isDocLoaded;
 
-    std::shared_ptr<lok::Document> _loKitDocument;
     std::string _docType;
     std::map<std::string, std::string> _lastDocStates;
     std::map<int, std::string> _lastDocEvents;
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 48902cb..4577003 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -31,6 +31,7 @@
 
 #define LOK_USE_UNSTABLE_API
 #include <LibreOfficeKit/LibreOfficeKitInit.h>
+#include <LibreOfficeKit/LibreOfficeKit.hxx>
 
 #include <Poco/Exception.h>
 #include <Poco/JSON/Object.h>
@@ -55,7 +56,6 @@
 #include "LOOLKit.hpp"
 #include "LOOLProtocol.hpp"
 #include "LOOLWebSocket.hpp"
-#include "LibreOfficeKit.hpp"
 #include "Log.hpp"
 #include "Png.hpp"
 #include "Rectangle.hpp"
@@ -295,10 +295,11 @@ public:
         _docPasswordType(PasswordType::ToView),
         _stop(false),
         _mutex(),
+        _documentMutex(),
         _isLoading(0)
     {
         LOG_INF("Document ctor for url [" << _url << "] on child [" << _jailId << "].");
-        assert(_loKit && _loKit->get());
+        assert(_loKit);
 
         _callbackThread.start(*this);
     }
@@ -479,7 +480,7 @@ public:
             return;
         }
 
-        std::unique_lock<std::mutex> lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_documentMutex);
         if (_loKitDocument->getViewsCount() <= 0)
         {
             LOG_ERR("Tile rendering requested without views.");
@@ -550,7 +551,7 @@ public:
             return;
         }
 
-        std::unique_lock<std::mutex> lock(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lock(_documentMutex);
         if (_loKitDocument->getViewsCount() <= 0)
         {
             LOG_ERR("Tile rendering requested without views.");
@@ -739,12 +740,12 @@ private:
     }
 
     /// Load a document (or view) and register callbacks.
-    std::shared_ptr<lok::Document> onLoad(const std::string& sessionId,
-                                          const std::string& uri,
-                                          const std::string& userName,
-                                          const std::string& docPassword,
-                                          const std::string& renderOpts,
-                                          const bool haveDocPassword) override
+    bool onLoad(const std::string& sessionId,
+                const std::string& uri,
+                const std::string& userName,
+                const std::string& docPassword,
+                const std::string& renderOpts,
+                const bool haveDocPassword) override
     {
         std::unique_lock<std::mutex> lock(_mutex);
 
@@ -765,13 +766,13 @@ private:
             load(sessionId, uri, userName, docPassword, renderOpts, haveDocPassword);
             if (!_loKitDocument || !_loKitDocument->get())
             {
-                return nullptr;
+                return false;
             }
         }
         catch (const std::exception& exc)
         {
             LOG_ERR("Exception while loading [" << uri << "] : " << exc.what());
-            return nullptr;
+            return false;
         }
 
         // Done loading, let the next one in (if any).
@@ -780,7 +781,7 @@ private:
         --_isLoading;
         _cvLoading.notify_one();
 
-        return _loKitDocument;
+        return true;
     }
 
     void onUnload(const ChildSession& session) override
@@ -797,7 +798,7 @@ private:
             return;
         }
 
-        std::unique_lock<std::mutex> lockLokDoc(_loKitDocument->getLock());
+        std::unique_lock<std::mutex> lockLokDoc(_documentMutex);
 
         _loKitDocument->setView(viewId);
         _loKitDocument->registerCallback(nullptr, nullptr);
@@ -907,7 +908,7 @@ private:
         std::map<std::string, int> viewColors;
 
         {
-            auto lock(_loKitDocument->getLock());
+            std::unique_lock<std::mutex> lock(_documentMutex);
 
             char* pValues = _loKitDocument->getCommandValues(".uno:TrackedChangeAuthors");
             colorValues = std::string(pValues == nullptr ? "" : pValues);
@@ -965,16 +966,12 @@ private:
             // This is the first time we are loading the document
             LOG_INF("Loading new document from URI: [" << uri << "] for session [" << sessionId << "].");
 
-            auto lock(_loKit->getLock());
+            _loKit->registerCallback(GlobalCallback, this);
 
-            if (LIBREOFFICEKIT_HAS(_loKit->get(), registerCallback))
-            {
-                _loKit->get()->pClass->registerCallback(_loKit->get(), GlobalCallback, this);
-                const auto flags = LOK_FEATURE_DOCUMENT_PASSWORD
-                                 | LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY
-                                 | LOK_FEATURE_PART_IN_INVALIDATION_CALLBACK;
-                _loKit->setOptionalFeatures(flags);
-            }
+            const auto flags = LOK_FEATURE_DOCUMENT_PASSWORD
+                             | LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY
+                             | LOK_FEATURE_PART_IN_INVALIDATION_CALLBACK;
+            _loKit->setOptionalFeatures(flags);
 
             // Save the provided password with us and the jailed url
             _haveDocPassword = haveDocPassword;
@@ -983,9 +980,9 @@ private:
             _isDocPasswordProtected = false;
 
             LOG_DBG("Calling lokit::documentLoad.");
-            _loKitDocument = _loKit->documentLoad(uri.c_str());
+            _loKitDocument.reset(_loKit->documentLoad(uri.c_str()));
             LOG_DBG("Returned lokit::documentLoad.");
-            auto l(_loKitDocument->getLock());
+            std::unique_lock<std::mutex> l(_documentMutex);
             lockLokDoc.swap(l);
 
             if (!_loKitDocument || !_loKitDocument->get())
@@ -1022,7 +1019,7 @@ private:
         }
         else
         {
-            auto l(_loKitDocument->getLock());
+            std::unique_lock<std::mutex> l(_documentMutex);
             lockLokDoc.swap(l);
 
             // Check if this document requires password
@@ -1236,6 +1233,18 @@ private:
         LOG_DBG("Thread finished.");
     }
 
+    /// Return access to the lok::Document instance.
+    std::shared_ptr<lok::Document> getLOKitDocument() override
+    {
+        return _loKitDocument;
+    }
+
+    /// Return access to the lok::Document instance.
+    std::mutex& getDocumentMutex() override
+    {
+        return _documentMutex;
+    }
+
 private:
     std::shared_ptr<lok::Office> _loKit;
     const std::string _jailId;
@@ -1259,6 +1268,11 @@ private:
 
     std::atomic<bool> _stop;
     mutable std::mutex _mutex;
+
+    /// Mutex guarding the lok::Document so that we can lock operations
+    /// like setting a view followed by a tile render, etc.
+    std::mutex _documentMutex;
+
     std::condition_variable _cvLoading;
     std::atomic_size_t _isLoading;
     std::map<int, std::unique_ptr<CallbackDescriptor>> _viewIdToCallbackDescr;
@@ -1435,14 +1449,14 @@ void lokit_main(const std::string& childRoot,
             }
 
             loKit = std::make_shared<lok::Office>(kit);
-            if (!loKit || !loKit->get())
+            if (!loKit)
             {
                 LOG_FTL("LibreOfficeKit initialization failed. Exiting.");
                 std::_Exit(Application::EXIT_SOFTWARE);
             }
         }
 
-        assert(loKit && loKit->get());
+        assert(loKit);
         LOG_INF("Process is ready.");
 
         // Open websocket connection between the child process and WSD.
diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am
index a87599d..865d3e7 100644
--- a/loolwsd/Makefile.am
+++ b/loolwsd/Makefile.am
@@ -98,7 +98,6 @@ noinst_HEADERS = Admin.hpp \
                  common/FileUtil.hpp \
                  common/SigUtil.hpp \
                  IoUtil.hpp \
-                 LibreOfficeKit.hpp \
                  Log.hpp \
                  LOKitHelper.hpp \
                  LOOLKit.hpp \
diff --git a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
index c7a2130..0b9535a 100644
--- a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
@@ -61,6 +61,7 @@ struct _LibreOfficeKitClass
     void (*freeError) (char* pFree);
 
 #if defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
+    /// @see lok::Office::registerCallback().
     void (*registerCallback) (LibreOfficeKit* pThis,
                               LibreOfficeKitCallback pCallback,
                               void* pData);
diff --git a/loolwsd/LibreOfficeKit.hpp b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.hxx
similarity index 69%
rename from loolwsd/LibreOfficeKit.hpp
rename to loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.hxx
index fe54938..447f44b 100644
--- a/loolwsd/LibreOfficeKit.hpp
+++ b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -7,15 +7,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#ifndef INCLUDED_LIBREOFFICEKIT_HPP
-#define INCLUDED_LIBREOFFICEKIT_HPP
+#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_HXX
+#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_HXX
 
-#define LOK_USE_UNSTABLE_API
-#include <LibreOfficeKit/LibreOfficeKit.h>
-#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <cstddef>
 
-#include "Log.hpp"
+#include "LibreOfficeKit.h"
+#include "LibreOfficeKitInit.h"
 
+/*
+ * The reasons this C++ code is not as pretty as it could be are:
+ *  a) provide a pure C API - that's useful for some people
+ *  b) allow ABI stability - C++ vtables are not good for that.
+ *  c) avoid C++ types as part of the API.
+ */
 namespace lok
 {
 
@@ -23,31 +28,17 @@ namespace lok
 class Document
 {
 private:
-    LibreOfficeKitDocument* _pDoc;
-    std::mutex _mutex;
+    LibreOfficeKitDocument* mpDoc;
 
 public:
     /// A lok::Document is typically created by the lok::Office::documentLoad() method.
     inline Document(LibreOfficeKitDocument* pDoc) :
-        _pDoc(pDoc),
-        _mutex()
-    {
-        Log::trace("lok::Document ctor.");
-    }
+        mpDoc(pDoc)
+    {}
 
     inline ~Document()
     {
-        Log::trace("lok::~Document dtor.");
-        _pDoc->pClass->destroy(_pDoc);
-    }
-
-    /// This lock must be held while calling
-    /// one or more members of this class if
-    /// the client is multi-threaded.
-    /// No member function takes this lock otherwise.
-    std::unique_lock<std::mutex> getLock()
-    {
-        return std::unique_lock<std::mutex>(_mutex);
+        mpDoc->pClass->destroy(mpDoc);
     }
 
     /**
@@ -65,16 +56,11 @@ public:
      */
     inline bool saveAs(const char* pUrl, const char* pFormat = NULL, const char* pFilterOptions = NULL)
     {
-        Log::trace() << "lok::Document: saveAs: URL: [" << pUrl << "], Format: [" << pFormat
-                     << "], FilterOptions: " << pFilterOptions << "." << Log::end;
-        return _pDoc->pClass->saveAs(_pDoc, pUrl, pFormat, pFilterOptions) != 0;
+        return mpDoc->pClass->saveAs(mpDoc, pUrl, pFormat, pFilterOptions) != 0;
     }
 
     /// Gives access to the underlying C pointer.
-    inline LibreOfficeKitDocument *get()
-    {
-        return _pDoc;
-    }
+    inline LibreOfficeKitDocument *get() { return mpDoc; }
 
 #if defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
     /**
@@ -84,7 +70,7 @@ public:
      */
     inline int getDocumentType()
     {
-        return _pDoc->pClass->getDocumentType(_pDoc);
+        return mpDoc->pClass->getDocumentType(mpDoc);
     }
 
     /**
@@ -95,7 +81,7 @@ public:
      */
     inline int getParts()
     {
-        return _pDoc->pClass->getParts(_pDoc);
+        return mpDoc->pClass->getParts(mpDoc);
     }
 
     /**
@@ -109,40 +95,36 @@ public:
      */
     inline char* getPartPageRectangles()
     {
-        return _pDoc->pClass->getPartPageRectangles(_pDoc);
+        return mpDoc->pClass->getPartPageRectangles(mpDoc);
     }
 
     /// Get the current part of the document.
-    /// Note: For Writer documents this always returns 0
-    /// since text docs have a single coordinate system.
     inline int getPart()
     {
-        return getDocumentType() == LOK_DOCTYPE_TEXT ? 0 : _pDoc->pClass->getPart(_pDoc);
+        return mpDoc->pClass->getPart(mpDoc);
     }
 
     /// Set the current part of the document.
     inline void setPart(int nPart)
     {
-        Log::trace() << "lok::Document: setPart: Part: " << nPart << "." << Log::end;
-        _pDoc->pClass->setPart(_pDoc, nPart);
+        mpDoc->pClass->setPart(mpDoc, nPart);
     }
 
     /// Get the current part's name.
     inline char* getPartName(int nPart)
     {
-        return _pDoc->pClass->getPartName(_pDoc, nPart);
+        return mpDoc->pClass->getPartName(mpDoc, nPart);
     }
 
     /// Get the current part's hash.
     inline char* getPartHash(int nPart)
     {
-        return _pDoc->pClass->getPartHash(_pDoc, nPart);
+        return mpDoc->pClass->getPartHash(mpDoc, nPart);
     }
 
     inline void setPartMode(int nMode)
     {
-        Log::trace() << "lok::Document: setPartMode: Mode: " << nMode << "." << Log::end;
-        _pDoc->pClass->setPartMode(_pDoc, nMode);
+        mpDoc->pClass->setPartMode(mpDoc, nMode);
     }
 
     /**
@@ -168,7 +150,7 @@ public:
                           const int nTileWidth,
                           const int nTileHeight)
     {
-        return _pDoc->pClass->paintTile(_pDoc, pBuffer, nCanvasWidth, nCanvasHeight,
+        return mpDoc->pClass->paintTile(mpDoc, pBuffer, nCanvasWidth, nCanvasHeight,
                                 nTilePosX, nTilePosY, nTileWidth, nTileHeight);
     }
 
@@ -179,13 +161,13 @@ public:
      */
     inline int getTileMode()
     {
-        return _pDoc->pClass->getTileMode(_pDoc);
+        return mpDoc->pClass->getTileMode(mpDoc);
     }
 
     /// Get the document sizes in TWIPs.
     inline void getDocumentSize(long* pWidth, long* pHeight)
     {
-        _pDoc->pClass->getDocumentSize(_pDoc, pWidth, pHeight);
+        mpDoc->pClass->getDocumentSize(mpDoc, pWidth, pHeight);
     }
 
     /**
@@ -210,8 +192,7 @@ public:
      */
     inline void initializeForRendering(const char* pArguments = NULL)
     {
-        Log::trace() << "lok::Document: initializeForRendering: Arguments: [" << pArguments << "]." << Log::end;
-        _pDoc->pClass->initializeForRendering(_pDoc, pArguments);
+        mpDoc->pClass->initializeForRendering(mpDoc, pArguments);
     }
 
     /**
@@ -223,7 +204,7 @@ public:
      */
     inline void registerCallback(LibreOfficeKitCallback pCallback, void* pData)
     {
-        _pDoc->pClass->registerCallback(_pDoc, pCallback, pData);
+        mpDoc->pClass->registerCallback(mpDoc, pCallback, pData);
     }
 
     /**
@@ -235,9 +216,7 @@ public:
      */
     inline void postKeyEvent(int nType, int nCharCode, int nKeyCode)
     {
-        Log::trace() << "lok::Document: postKeyEvent: Type=" << nType
-                     << ", CharCode=" << nCharCode << ", KeyCode=" << nKeyCode << Log::end;
-        _pDoc->pClass->postKeyEvent(_pDoc, nType, nCharCode, nKeyCode);
+        mpDoc->pClass->postKeyEvent(mpDoc, nType, nCharCode, nKeyCode);
     }
 
     /**
@@ -252,10 +231,7 @@ public:
      */
     inline void postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
     {
-        Log::trace() << "lok::Document: postMouseEvent: Type=" << nType
-                     << ", X=" << nX << ", nY=" << nY << ", Count=" << nCount
-                     << ", Buttons=" << nButtons << ", Modifier=" << nModifier << Log::end;
-        _pDoc->pClass->postMouseEvent(_pDoc, nType, nX, nY, nCount, nButtons, nModifier);
+        mpDoc->pClass->postMouseEvent(mpDoc, nType, nX, nY, nCount, nButtons, nModifier);
     }
 
     /**
@@ -281,10 +257,7 @@ public:
      */
     inline void postUnoCommand(const char* pCommand, const char* pArguments = NULL, bool bNotifyWhenFinished = false)
     {
-        Log::trace() << "lok::Document: postUnoCommand: Command=" << pCommand
-                     << ", Args=" << (pArguments ? pArguments : "''")
-                     << ", NotifyWhenFinished=" << bNotifyWhenFinished << Log::end;
-        _pDoc->pClass->postUnoCommand(_pDoc, pCommand, pArguments, bNotifyWhenFinished);
+        mpDoc->pClass->postUnoCommand(mpDoc, pCommand, pArguments, bNotifyWhenFinished);
     }
 
     /**
@@ -296,7 +269,7 @@ public:
      */
     inline void setTextSelection(int nType, int nX, int nY)
     {
-        _pDoc->pClass->setTextSelection(_pDoc, nType, nX, nY);
+        mpDoc->pClass->setTextSelection(mpDoc, nType, nX, nY);
     }
 
     /**
@@ -307,7 +280,7 @@ public:
      */
     inline char* getTextSelection(const char* pMimeType, char** pUsedMimeType = NULL)
     {
-        return _pDoc->pClass->getTextSelection(_pDoc, pMimeType, pUsedMimeType);
+        return mpDoc->pClass->getTextSelection(mpDoc, pMimeType, pUsedMimeType);
     }
 
     /**
@@ -319,7 +292,7 @@ public:
      */
     inline bool paste(const char* pMimeType, const char* pData, size_t nSize)
     {
-        return _pDoc->pClass->paste(_pDoc, pMimeType, pData, nSize);
+        return mpDoc->pClass->paste(mpDoc, pMimeType, pData, nSize);
     }
 
     /**
@@ -331,7 +304,7 @@ public:
      */
     inline void setGraphicSelection(int nType, int nX, int nY)
     {
-        _pDoc->pClass->setGraphicSelection(_pDoc, nType, nX, nY);
+        mpDoc->pClass->setGraphicSelection(mpDoc, nType, nX, nY);
     }
 
     /**
@@ -339,7 +312,7 @@ public:
      */
     inline void resetSelection()
     {
-        _pDoc->pClass->resetSelection(_pDoc);
+        mpDoc->pClass->resetSelection(mpDoc);
     }
 
     /**
@@ -350,7 +323,7 @@ public:
      */
     inline char* getCommandValues(const char* pCommand)
     {
-        return _pDoc->pClass->getCommandValues(_pDoc, pCommand);
+        return mpDoc->pClass->getCommandValues(mpDoc, pCommand);
     }
 
     /**
@@ -367,11 +340,7 @@ public:
             int nTileTwipWidth,
             int nTileTwipHeight)
     {
-        Log::trace() << "lok::Document: setClientZoom: TilePixelWidth: " << nTilePixelWidth
-                     << ", TilePixelHeight: " << nTileTwipHeight
-                     <<  ", TileTwipWidth: " << nTileTwipWidth
-                     << ", TileTwipHeight: " << nTileTwipHeight << "." << Log::end;
-        _pDoc->pClass->setClientZoom(_pDoc, nTilePixelWidth, nTilePixelHeight, nTileTwipWidth, nTileTwipHeight);
+        mpDoc->pClass->setClientZoom(mpDoc, nTilePixelWidth, nTilePixelHeight, nTileTwipWidth, nTileTwipHeight);
     }
 
     /**
@@ -386,10 +355,7 @@ public:
      */
     inline void setClientVisibleArea(int nX, int nY, int nWidth, int nHeight)
     {
-        Log::trace() << "lok::Document: setClientVisibleArea: X: " << nX
-                     << ", Y: " << nY << ", Width: " << nWidth
-                     << ", Height: " << nHeight << "." << Log::end;
-        _pDoc->pClass->setClientVisibleArea(_pDoc, nX, nY, nWidth, nHeight);
+        mpDoc->pClass->setClientVisibleArea(mpDoc, nX, nY, nWidth, nHeight);
     }
 
     /**
@@ -399,8 +365,7 @@ public:
      */
     int createView()
     {
-        Log::trace() << "lok::Document: createView" << Log::end;
-        return _pDoc->pClass->createView(_pDoc);
+        return mpDoc->pClass->createView(mpDoc);
     }
 
     /**
@@ -409,8 +374,7 @@ public:
      */
     void destroyView(int nId)
     {
-        Log::trace() << "lok::Document: destroyView: " << nId << Log::end;
-        _pDoc->pClass->destroyView(_pDoc, nId);
+        mpDoc->pClass->destroyView(mpDoc, nId);
     }
 
     /**
@@ -419,9 +383,7 @@ public:
      */
     void setView(int nId)
     {
-        Log::trace() << "lok::Document: setView: " << nId << Log::end;
-        assert(nId >= 0 && "ViewID must be non-negative.");
-        _pDoc->pClass->setView(_pDoc, nId);
+        mpDoc->pClass->setView(mpDoc, nId);
     }
 
     /**
@@ -430,7 +392,7 @@ public:
      */
     int getView()
     {
-        return _pDoc->pClass->getView(_pDoc);
+        return mpDoc->pClass->getView(mpDoc);
     }
 
     /**
@@ -438,26 +400,11 @@ public:
      */
     inline int getViewsCount()
     {
-        return _pDoc->pClass->getViewsCount(_pDoc);
-    }
-
-    /**
-     * Returns the viewID for each existing view. Since viewIDs are not reused,
-     * viewIDs are not the same as the index of the view in the view array over
-     * time. Use getViewsCount() to know the minimal nSize that's large enough.
-     *
-     * @param pArray the array to write the viewIDs into
-     * @param nSize the size of pArray
-     * @returns true if pArray was large enough and result is written, false
-     * otherwise.
-     */
-    inline int getViewIds(int* pArray, size_t nSize)
-    {
-        return _pDoc->pClass->getViewIds(_pDoc, pArray, nSize);
+        return mpDoc->pClass->getViewsCount(mpDoc);
     }
 
     /**
-     * Paints a font name to be displayed in the font list
+     * Paints a font name or character if provided to be displayed in the font list
      * @param pFontName the font to be painted
      */
     inline unsigned char* renderFont(const char *pFontName,
@@ -465,7 +412,7 @@ public:
                           int *pFontWidth,
                           int *pFontHeight)
     {
-        return _pDoc->pClass->renderFont(_pDoc, pFontName, pChar, pFontWidth, pFontHeight);
+        return mpDoc->pClass->renderFont(mpDoc, pFontName, pChar, pFontWidth, pFontHeight);
     }
 
     /**
@@ -483,12 +430,28 @@ public:
                               const int nTileWidth,
                               const int nTileHeight)
     {
-        return _pDoc->pClass->paintPartTile(_pDoc, pBuffer, nPart,
+        return mpDoc->pClass->paintPartTile(mpDoc, pBuffer, nPart,
                                             nCanvasWidth, nCanvasHeight,
                                             nTilePosX, nTilePosY,
                                             nTileWidth, nTileHeight);
     }
 
+    /**
+     * Returns the viewID for each existing view. Since viewIDs are not reused,
+     * viewIDs are not the same as the index of the view in the view array over
+     * time. Use getViewsCount() to know the minimal nSize that's large enough.
+     *
+     * @param pArray the array to write the viewIDs into
+     * @param nSize the size of pArray
+     * @returns true if pArray was large enough and result is written, false
+     * otherwise.
+     */
+    inline bool getViewIds(int* pArray,
+                           size_t nSize)
+    {
+        return mpDoc->pClass->getViewIds(mpDoc, pArray, nSize);
+    }
+
 #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
 };
 
@@ -496,44 +459,17 @@ public:
 class Office
 {
 private:
-    LibreOfficeKit* _pOffice;
-    std::mutex _mutex;
+    LibreOfficeKit* mpThis;
 
 public:
     /// A lok::Office is typically created by the lok_cpp_init() function.
     inline Office(LibreOfficeKit* pThis) :
-        _pOffice(pThis),
-        _mutex()
-    {
-        Log::trace("lok::Office ctor.");
-        assert(_pOffice);
-    }
+        mpThis(pThis)
+    {}
 
     inline ~Office()
     {
-        std::unique_lock<std::mutex> lock(_mutex);
-        Log::trace("lok::~Office dtor.");
-        try
-        {
-            _pOffice->pClass->destroy(_pOffice);
-        }
-        catch (const std::exception& ex)
-        {
-            LOG_ERR("Exception while destroying LibreOfficeKit instance: " << ex.what());
-        }
-    }
-
-    /// This lock must be held while calling
-    /// one or more member of this class.
-    std::unique_lock<std::mutex> getLock()
-    {
-        return std::unique_lock<std::mutex>(_mutex);
-    }
-
-    /// Gives access to the underlying C pointer.
-    inline LibreOfficeKit* get()
-    {
-        return _pOffice;
+        mpThis->pClass->destroy(mpThis);
     }
 
     /**
@@ -541,37 +477,53 @@ public:
      *
      * @param pUrl the URL of the document to load
      * @param pFilterOptions options for the import filter, e.g. SkipImages.
+     * @since pFilterOptions argument added in LibreOffice 5.0
      */
-    inline std::shared_ptr<Document> documentLoad(const char* pUrl, const char* pFilterOptions = NULL)
+    inline Document* documentLoad(const char* pUrl, const char* pFilterOptions = NULL)
     {
-        Log::trace() << "lok::Office: documentLoad: URL: [" << pUrl
-                     << "], FilterOptions: [" << pFilterOptions
-                     << "]." << Log::end;
         LibreOfficeKitDocument* pDoc = NULL;
 
-        if (LIBREOFFICEKIT_HAS(_pOffice, documentLoadWithOptions))
-            pDoc = _pOffice->pClass->documentLoadWithOptions(_pOffice, pUrl, pFilterOptions);
+        if (LIBREOFFICEKIT_HAS(mpThis, documentLoadWithOptions))
+            pDoc = mpThis->pClass->documentLoadWithOptions(mpThis, pUrl, pFilterOptions);
         else
-            pDoc = _pOffice->pClass->documentLoad(_pOffice, pUrl);
+            pDoc = mpThis->pClass->documentLoad(mpThis, pUrl);
 
-        return std::make_shared<lok::Document>(pDoc);
+        if (pDoc == NULL)
+            return NULL;
+
+        return new Document(pDoc);
     }
 
     /// Returns the last error as a string, the returned pointer has to be freed by the caller.
     inline char* getError()
     {
-        return _pOffice->pClass->getError(_pOffice);
+        return mpThis->pClass->getError(mpThis);
     }
 
-    /// Frees the memory pointed to by pFree.
+    /**
+     * Frees the memory pointed to by pFree.
+     *
+     * @since LibreOffice 5.2
+     */
     inline void freeError(char* pFree)
     {
-        _pOffice->pClass->freeError(pFree);
+        mpThis->pClass->freeError(pFree);
     }
 
-
 #if defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
     /**
+     * Registers a callback. LOK will invoke this function when it wants to
+     * inform the client about events.
+     *
+     * @param pCallback the callback to invoke
+     * @param pData the user data, will be passed to the callback on invocation
+     */
+    inline void registerCallback(LibreOfficeKitCallback pCallback, void* pData)
+    {
+        mpThis->pClass->registerCallback(mpThis, pCallback, pData);
+    }
+
+    /**
      * Returns details of filter types.
      *
      * Example returned string:
@@ -587,7 +539,7 @@ public:
      */
     inline char* getFilterTypes()
     {
-        return _pOffice->pClass->getFilterTypes(_pOffice);
+        return mpThis->pClass->getFilterTypes(mpThis);
     }
 
     /**
@@ -597,7 +549,7 @@ public:
      */
     void setOptionalFeatures(uint64_t features)
     {
-        return _pOffice->pClass->setOptionalFeatures(_pOffice, features);
+        return mpThis->pClass->setOptionalFeatures(mpThis, features);
     }
 
     /**
@@ -621,26 +573,38 @@ public:
      */
     inline void setDocumentPassword(char const* pURL, char const* pPassword)
     {
-        _pOffice->pClass->setDocumentPassword(_pOffice, pURL, pPassword);
+        mpThis->pClass->setDocumentPassword(mpThis, pURL, pPassword);
     }
 
     /**
      * Get version information of the LOKit process
      *
-     * @returns string containing version information in format:
-     * PRODUCT_NAME PRODUCT_VERSION PRODUCT_EXTENSION BUILD_ID
+     * @returns JSON string containing version information in format:
+     * {ProductName: <>, ProductVersion: <>, ProductExtension: <>, BuildId: <>}
      *
-     * Eg: LibreOffice 5.3 .0.0 alpha0 <commit hash>
+     * Eg: {"ProductName": "LibreOffice",
+     * "ProductVersion": "5.3",
+     * "ProductExtension": ".0.0.alpha0",
+     * "BuildId": "<full 40 char git hash>"}
      */
     inline char* getVersionInfo()
     {
-        return _pOffice->pClass->getVersionInfo(_pOffice);
+        return mpThis->pClass->getVersionInfo(mpThis);
     }
 #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
 };
 
+/// Factory method to create a lok::Office instance.
+inline Office* lok_cpp_init(const char* pInstallPath, const char* pUserProfileUrl = NULL)
+{
+    LibreOfficeKit* pThis = lok_init_2(pInstallPath, pUserProfileUrl);
+    if (pThis == NULL || pThis->pClass->nSize == 0)
+        return NULL;
+    return new ::lok::Office(pThis);
+}
+
 }
 
-#endif // INCLUDED_LIBREOFFICEKIT_HPP
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/test/WhiteBoxTests.cpp b/loolwsd/test/WhiteBoxTests.cpp
index fd3814a..2224619 100644
--- a/loolwsd/test/WhiteBoxTests.cpp
+++ b/loolwsd/test/WhiteBoxTests.cpp
@@ -154,26 +154,33 @@ class DummyDocument : public IDocumentManager
 {
     std::shared_ptr<TileQueue> _tileQueue;
     std::mutex _mutex;
+    std::mutex _documentMutex;
 public:
     DummyDocument()
         : _tileQueue(new TileQueue()),
-        _mutex()
+        _mutex(),
+        _documentMutex()
     {
     }
-    std::shared_ptr<lok::Document> onLoad(const std::string& /*sessionId*/,
-                                          const std::string& /*jailedFilePath*/,
-                                          const std::string& /*userName*/,
-                                          const std::string& /*docPassword*/,
-                                          const std::string& /*renderOpts*/,
-                                          const bool /*haveDocPassword*/) override
+    bool onLoad(const std::string& /*sessionId*/,
+                const std::string& /*jailedFilePath*/,
+                const std::string& /*userName*/,
+                const std::string& /*docPassword*/,
+                const std::string& /*renderOpts*/,
+                const bool /*haveDocPassword*/) override
     {
-        return nullptr;
+        return false;
     }
 
     void onUnload(const ChildSession& /*session*/) override
     {
     }
 
+    std::shared_ptr<lok::Document> getLOKitDocument() override
+    {
+        return nullptr;
+    }
+
     void notifyViewInfo(const std::vector<int>& /*viewIds*/) override
     {
     }
@@ -188,6 +195,11 @@ public:
         return _mutex;
     }
 
+    std::mutex& getDocumentMutex() override
+    {
+        return _mutex;
+    }
+
     std::shared_ptr<TileQueue>& getTileQueue() override
     {
         return _tileQueue;


More information about the Libreoffice-commits mailing list