loleaflet/dist/toolbar/toolbar.js | 5 +- loleaflet/src/control/Control.Menubar.js | 10 ++-- loleaflet/src/control/Toolbar.js | 12 ----- wsd/ClientSession.cpp | 8 +++ wsd/DocumentBroker.cpp | 70 ++++++++++++++++--------------- wsd/DocumentBroker.hpp | 6 +- wsd/protocol.txt | 10 +++- 7 files changed, 67 insertions(+), 54 deletions(-)
New commits: commit 41942b923cde9adfea679288f8a818e9e87b825f Author: Pranav Kant <pran...@collabora.co.uk> Date: Mon May 15 11:29:04 2017 +0530 wsd: Save wrapper over .uno:Save Document broker needs to know when the save request is sent and when the save finished. It uses these parameters to avoid shutting down document, in the document broker main polling loop, if save is already going on. But direct .uno:Save commands issued from loleaflet precludes document broker to keep track of it - in this case a .uno:Save command issued from loleaflet followed by shutting-down the wsd will prevent saving the document to storage, if document is huge enough and LO core takes a bit of time to save it. A save wrapper command, 'save', ensures that document broker is aware of all such save requests (_saveRequestTime member variable) and doesn't close the document until we completely save it (to storage and other cleanups). Change-Id: I5ec73d45adff23b2e7543e93dfd0624a5e5af46d (cherry picked from commit 1cb75cbcb8c87481bf341c5ac058a36c13529dc8) Reviewed-on: https://gerrit.libreoffice.org/37643 Reviewed-by: Jan Holesovsky <ke...@collabora.com> Tested-by: Jan Holesovsky <ke...@collabora.com> diff --git a/loleaflet/dist/toolbar/toolbar.js b/loleaflet/dist/toolbar/toolbar.js index bc2d9cd0..11ad3244 100644 --- a/loleaflet/dist/toolbar/toolbar.js +++ b/loleaflet/dist/toolbar/toolbar.js @@ -218,6 +218,9 @@ function onClick(id, item, subItem) { map.toggleCommandState(item.uno); } } + else if (id === 'save') { + map.save(true, true); + } else if (id === 'repair') { map._socket.sendMessage('commandvalues command=.uno:DocumentRepair'); } @@ -451,7 +454,7 @@ $(function () { name: 'toolbar-up', items: [ {type: 'html', id: 'left'}, - {type: 'button', id: 'save', img: 'save', hint: _('Save'), uno: 'Save'}, + {type: 'button', id: 'save', img: 'save', hint: _('Save')}, {type: 'break', id: 'savebreak'}, {type: 'button', id: 'undo', img: 'undo', hint: _('Undo'), uno: 'Undo'}, {type: 'button', id: 'redo', img: 'redo', hint: _('Redo'), uno: 'Redo'}, diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js index 89048a3b..8206ab5c 100644 --- a/loleaflet/src/control/Control.Menubar.js +++ b/loleaflet/src/control/Control.Menubar.js @@ -8,7 +8,7 @@ L.Control.Menubar = L.Control.extend({ options: { text: [ {name: _('File'), id: 'file', type: 'menu', menu: [ - {name: _('Save'), id: 'save', type: 'unocommand', uno: '.uno:Save'}, + {name: _('Save'), id: 'save', type: 'action'}, {name: _('Print'), id: 'print', type: 'action'}, {name: _('See revision history'), id: 'rev-history', type: 'action'}, {name: _('Download as'), id: 'downloadas', type: 'menu', menu: [ @@ -172,7 +172,7 @@ L.Control.Menubar = L.Control.extend({ presentation: [ {name: _('File'), id: 'file', type: 'menu', menu: [ - {name: _('Save'), id: 'save', type: 'unocommand', uno: '.uno:Save'}, + {name: _('Save'), id: 'save', type: 'action'}, {name: _('Print'), id: 'print', type: 'action'}, {name: _('See revision history'), id: 'rev-history', type: 'action'}, {name: _('Download as'), id: 'downloadas', type: 'menu', menu: [ @@ -232,7 +232,7 @@ L.Control.Menubar = L.Control.extend({ spreadsheet: [ {name: _('File'), id: 'file', type: 'menu', menu: [ - {name: _('Save'), id: 'save', type: 'unocommand', uno: '.uno:Save'}, + {name: _('Save'), id: 'save', type: 'action'}, {name: _('Print'), id: 'print', type: 'action'}, {name: _('See revision history'), id: 'rev-history', type: 'action'}, {name: _('Download as'), id:'downloadas', type: 'menu', menu: [ @@ -417,7 +417,9 @@ L.Control.Menubar = L.Control.extend({ }, _executeAction: function(id) { - if (id === 'print') { + if (id === 'save') { + map.save(true, true); + } else if (id === 'print') { map.print(); } else if (id.startsWith('downloadas-')) { var format = id.substring('downloadas-'.length); diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js index 8d229f53..681a8ecc 100644 --- a/loleaflet/src/control/Toolbar.js +++ b/loleaflet/src/control/Toolbar.js @@ -131,17 +131,7 @@ L.Map.include({ }, save: function(dontTerminateEdit, dontSaveIfUnmodified) { - var args = { - DontTerminateEdit: { - type: 'boolean', - value: !!dontTerminateEdit - }, - DontSaveIfUnmodified: { - type: 'boolean', - value: !!dontSaveIfUnmodified - } - }; - this.sendUnoCommand('.uno:Save', args); + this._socket.sendMessage('save dontTerminateEdit=' + (dontTerminateEdit ? 1 : 0) + ' dontSaveIfUnmodified=' + (dontSaveIfUnmodified ? 1 : 0)); }, sendUnoCommand: function (command, json) { diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index c1693c60..90a21aa2 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -203,6 +203,14 @@ bool ClientSession::_handleInput(const char *buffer, int length) { return sendCombinedTiles(buffer, length, tokens, docBroker); } + else if (tokens[0] == "save") + { + int dontTerminateEdit = 1; + int dontSaveIfUnmodified = 1; + getTokenInteger(tokens[1], "dontTerminateEdit", dontTerminateEdit); + getTokenInteger(tokens[2], "dontSaveIfUnmodified", dontSaveIfUnmodified); + docBroker->sendUnoSave(getId(), dontTerminateEdit != 0, dontSaveIfUnmodified != 0); + } else { if (!filterMessage(firstLine)) diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index 0dac41b5..2c66154e 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -700,11 +700,29 @@ bool DocumentBroker::autoSave(const bool force) // Remember the last save time, since this is the predicate. LOG_TRC("Checking to autosave [" << _docKey << "]."); + // Which session to use when auto saving ? + std::string savingSessionId; + for (auto& sessionIt : _sessions) + { + // Save the document using first session available ... + if (savingSessionId.empty()) + { + savingSessionId = sessionIt.second->getId(); + } + + // or if any of the sessions is document owner, use that. + if (sessionIt.second->isDocumentOwner()) + { + savingSessionId = sessionIt.second->getId(); + break; + } + } + bool sent = false; if (force) { LOG_TRC("Sending forced save command for [" << _docKey << "]."); - sent = sendUnoSave(true); + sent = sendUnoSave(savingSessionId); } else if (_isModified) { @@ -719,37 +737,20 @@ bool DocumentBroker::autoSave(const bool force) timeSinceLastSaveMs >= AutoSaveDurationMs) { LOG_TRC("Sending timed save command for [" << _docKey << "]."); - sent = sendUnoSave(true); + sent = sendUnoSave(savingSessionId); } } return sent; } -bool DocumentBroker::sendUnoSave(const bool dontSaveIfUnmodified) +bool DocumentBroker::sendUnoSave(const std::string& sessionId, bool dontTerminateEdit, bool dontSaveIfUnmodified) { assertCorrectThread(); - LOG_INF("Autosave triggered for doc [" << _docKey << "]."); + LOG_INF("Saving doc [" << _docKey << "]."); - std::shared_ptr<ClientSession> savingSession; - for (auto& sessionIt : _sessions) - { - // Save the document using first session available ... - if (!savingSession) - { - savingSession = sessionIt.second; - } - - // or if any of the sessions is document owner, use that. - if (sessionIt.second->isDocumentOwner()) - { - savingSession = sessionIt.second; - break; - } - } - - if (savingSession) + if (_sessions.find(sessionId) != _sessions.end()) { // Invalidate the timestamp to force persisting. _lastFileModifiedTime = Poco::Timestamp::fromEpochTime(0); @@ -760,18 +761,21 @@ bool DocumentBroker::sendUnoSave(const bool dontSaveIfUnmodified) // arguments init oss << "{"; - // Mention DontTerminateEdit always - oss << "\"DontTerminateEdit\":" - << "{" - << "\"type\":\"boolean\"," - << "\"value\":true" - << "}"; + if (dontTerminateEdit) + { + oss << "\"DontTerminateEdit\":" + << "{" + << "\"type\":\"boolean\"," + << "\"value\":true" + << "}"; + } - // Mention DontSaveIfUnmodified if (dontSaveIfUnmodified) { - oss << "," - << "\"DontSaveIfUnmodified\":" + if (dontTerminateEdit) + oss << ","; + + oss << "\"DontSaveIfUnmodified\":" << "{" << "\"type\":\"boolean\"," << "\"value\":true" @@ -784,12 +788,12 @@ bool DocumentBroker::sendUnoSave(const bool dontSaveIfUnmodified) const auto saveArgs = oss.str(); LOG_TRC(".uno:Save arguments: " << saveArgs); const auto command = "uno .uno:Save " + saveArgs; - forwardToChild(savingSession->getId(), command); + forwardToChild(sessionId, command); _lastSaveRequestTime = std::chrono::steady_clock::now(); return true; } - LOG_ERR("Failed to auto-save doc [" << _docKey << "]: No valid sessions."); + LOG_ERR("Failed to save doc [" << _docKey << "]: No valid sessions."); return false; } diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp index 3f7ebc67..46481cba 100644 --- a/wsd/DocumentBroker.hpp +++ b/wsd/DocumentBroker.hpp @@ -335,14 +335,14 @@ public: return std::chrono::duration_cast<std::chrono::seconds>(duration).count(); } + /// Sends the .uno:Save command to LoKit. + bool sendUnoSave(const std::string& sessionId, bool dontTerminateEdit = true, bool dontSaveIfUnmodified = true); + private: /// This gracefully terminates the connection /// with the child and cleans up ChildProcess etc. void terminateChild(const std::string& closeReason, const bool rude); - /// Sends the .uno:Save command to LoKit. - bool sendUnoSave(const bool dontSaveIfUnmodified); - /// Saves the doc to the storage. bool saveToStorageInternal(const std::string& sesionId, bool success, const std::string& result = ""); diff --git a/wsd/protocol.txt b/wsd/protocol.txt index 0c13bca7..d1de4ab3 100644 --- a/wsd/protocol.txt +++ b/wsd/protocol.txt @@ -152,6 +152,14 @@ uno <command> <command> is a line of text. +save dontTerminateEdit=<value> dontSaveIfUnmodified=<value> + + A wrapper over UNO save command. A non-zero <value> is considered true. + 'dontTerminateEdit' means not terminating the edit session in + spreadsheets when saving the document. In most cases, you should set it to + non-zero. 'dontSaveIfUnmodified' when set to non-zero skips saving the document when it is + unmodified. + clientvisiblearea x=<x> y=<y> width=<width> height=<height> Invokes lok::Document::setClientVisibleArea(). @@ -626,5 +634,3 @@ lokitversion <JSON string> "ProductVersion": "5.3", "ProductExtension": ".0.0.alpha0", "BuildId": "<full 40 char git hash>"} - - _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits