[Libreoffice-commits] online.git: 7 commits - loleaflet/src wsd/ClientSession.cpp wsd/ClientSession.hpp wsd/DocumentBroker.cpp wsd/Storage.cpp wsd/Storage.hpp

Ashod Nakashian (via logerrit) logerrit at kemper.freedesktop.org
Tue Jan 28 17:28:48 UTC 2020


 loleaflet/src/control/Control.LokDialog.js    |   20 ++++----
 loleaflet/src/control/Control.Toolbar.js      |   12 ++---
 loleaflet/src/layer/tile/TileLayer.js         |    4 -
 loleaflet/src/map/Map.js                      |   47 +++++++-------------
 loleaflet/src/map/handler/Map.TouchGesture.js |   17 ++++---
 wsd/ClientSession.cpp                         |   14 +++++-
 wsd/ClientSession.hpp                         |    5 ++
 wsd/DocumentBroker.cpp                        |   17 +++----
 wsd/Storage.cpp                               |   53 ++++++++++++++++-------
 wsd/Storage.hpp                               |   59 +++++++++++++++++++-------
 10 files changed, 153 insertions(+), 95 deletions(-)

New commits:
commit 7c1153d30a96320a72ddb7de96f0011e7058be32
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sun Jan 26 17:21:51 2020 -0500
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Jan 28 18:10:14 2020 +0100

    leaflet: double-tap to show keyboard on mobile
    
    On mobile, we now do not show the keyboard by default
    when the user taps the cell in Calc or a text-area in Impress.
    Instead, the user should double-tap. This is especially useful
    when the user selects the cell on first tap, then double-tap to edit.
    As for Impress, editing-mode is enabled only by double-clicking,
    so showing the keyboard on mobile on single tap is not helpful
    as the user can't edit just yet. So it makes sense to show
    the keyboard only on double-tap, when the slide is in text
    editing mode.
    
    On desktop and for other document the behavior is unchanged.
    
    Change-Id: I4206291f60656391d061387f7bbad1b6e3caf80d

diff --git a/loleaflet/src/control/Control.LokDialog.js b/loleaflet/src/control/Control.LokDialog.js
index 9804e5d65..4779f4ed9 100644
--- a/loleaflet/src/control/Control.LokDialog.js
+++ b/loleaflet/src/control/Control.LokDialog.js
@@ -411,8 +411,6 @@ L.Control.LokDialog = L.Control.extend({
 		this._map.setWinId(dlgId);
 		if (dlgId in this._dialogs) {
 			this._map.focus();
-		} else {
-			this._map.blur();
 		}
 	},
 
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index f5fb704a8..0b4926a43 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -2091,8 +2091,8 @@ L.TileLayer = L.GridLayer.extend({
 
 		this._map._textInput.showCursor();
 		if (this._map.editorHasFocus() /* && !L.Browser.mobile */) {
-			// On mobile, this is causing some key input to get lost.
-			this._map.focus();
+			// User is editing, show the keyboard.
+			this._map.focus(true);
 		}
 	},
 
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 6a2e99f3e..45ab9273a 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -904,12 +904,13 @@ L.Map = L.Evented.extend({
 		return this.layerPointToLatLng(this.mouseEventToLayerPoint(e));
 	},
 
-	// Give the focus to the text input to accept keyboard input.
-	// On mobile, it will show the virtual keyboard.
-	focus: function () {
-		//TODO: we should check if focus is going to edit the doc in
-		//TODO: read-only mode and prevent it (but allow for searching).
+	// Give the focus to the text input.
+	// @acceptInput (on mobile only) true if we want to
+	// accept key input, and show the virtual keyboard.
+	focus: function (acceptInput) {
 		this._textInput.focus();
+		if (window.mode.isMobile() && acceptInput !== true)
+			this.blur();
 	},
 
 	// Lose focus to stop accepting keyboard input.
diff --git a/loleaflet/src/map/handler/Map.TouchGesture.js b/loleaflet/src/map/handler/Map.TouchGesture.js
index 78fa4affc..7d9d07f5d 100644
--- a/loleaflet/src/map/handler/Map.TouchGesture.js
+++ b/loleaflet/src/map/handler/Map.TouchGesture.js
@@ -322,11 +322,8 @@ L.Map.TouchGesture = L.Handler.extend({
 			docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, 1, 1, 0);
 			docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 1, 1, 0);
 
-			if (this._state === L.Map.TouchGesture.MARKER || (this._state === L.Map.TouchGesture.GRAPHIC && !docLayer._isCursorVisible)) {
-				this._map.blur();
-			} else if (!this._map.hasFocus()) {
-				this._map.focus();
-			}
+			// Take focus, but keyboard show only in Writer (double-tap to edit Calc/Impress).
+			this._map.focus(this._map._docLayer._docType === 'text');
 		}
 	},
 
@@ -337,8 +334,14 @@ L.Map.TouchGesture = L.Handler.extend({
 		    latlng = this._map.layerPointToLatLng(layerPoint),
 		    mousePos = this._map._docLayer._latLngToTwips(latlng);
 
-		this._map._docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, 2, 1, 0);
-		this._map._docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 2, 1, 0);
+		var docLayer = this._map._docLayer;
+		if (docLayer) {
+			docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, 2, 1, 0);
+			docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 2, 1, 0);
+
+			// Show keyboard.
+			this._map.focus(true);
+		}
 	},
 
 	_onTripleTap: function (e) {
commit c3d2b1233e3d8073468ea69552f55c72488a7d5d
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sat Jan 25 13:13:49 2020 -0500
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Jan 28 18:10:14 2020 +0100

    leaflet: remove delayed cursor update and simplify
    
    Change-Id: Ifcc165562d1f7aba611bb578688d9c5203681765

diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 0f69fe74c..6a2e99f3e 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -246,7 +246,7 @@ L.Map = L.Evented.extend({
 		this.on('editorgotfocus', this._onEditorGotFocus, this);
 
 		// Fired to signal that the input focus is being changed.
-		this.on('changefocuswidget', this._changeFocusWidget, this);
+		this.on('changefocuswidget', this._onChangeFocusWidget, this);
 
 		// View info (user names and view ids)
 		this._viewInfo = {};
@@ -1334,8 +1334,8 @@ L.Map = L.Evented.extend({
 		}, map.options.outOfFocusTimeoutSecs * 1000);
 	},
 
-	// Change the focus to a dialog.
-	onFocusDialog: function onFocusDialog(dialog, winId) {
+	// Change the focus to a dialog or editor.
+	_changeFocusWidget: function (dialog, winId) {
 		if (!this._loaded) { return; }
 
 		this._winId = winId;
@@ -1353,22 +1353,7 @@ L.Map = L.Evented.extend({
 
 	// The editor got focus (probably a dialog closed or user clicked to edit).
 	_onEditorGotFocus: function() {
-		if (!this._loaded) { return; }
-
-		this._winId = 0;
-		this._activeDialog = null;
-
-		var doclayer = this._docLayer;
-		if (doclayer)
-		{
-			// we restore the old cursor position by a small delay, so that if the user clicks
-			// inside the document we skip to restore it, so that the user does not see the cursor
-			// jumping from the old position to the new one
-			setTimeout(function () {
-				console.debug('apply focus change in timeout');
-				doclayer._updateCursorAndOverlay();
-			}, 300);
-		}
+		this._changeFocusWidget(null, 0);
 	},
 
 	// Our browser tab got focus.
@@ -1383,12 +1368,12 @@ L.Map = L.Evented.extend({
 		this._activate();
 	},
 
-	// Focus is being changed, update states.
-	_changeFocusWidget: function (e) {
+	// Event to change the focus to dialog or editor.
+	_onChangeFocusWidget: function (e) {
 		if (e.winId === 0) {
 			this._onEditorGotFocus();
 		} else {
-			this.onFocusDialog(e.dialog, e.winId);
+			this._changeFocusWidget(e.dialog, e.winId);
 		}
 	},
 
commit aa921021007a8b49066dec5375b65e8a9bb4ba71
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sat Jan 18 11:15:07 2020 -0500
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Jan 28 18:10:14 2020 +0100

    leaflet: focus the dialog/sidebar even when the cursor is not visible
    
    Change-Id: I96963957986ba29cc55670dd6ef79a0bf39a9132

diff --git a/loleaflet/src/control/Control.LokDialog.js b/loleaflet/src/control/Control.LokDialog.js
index 13b261e5e..9804e5d65 100644
--- a/loleaflet/src/control/Control.LokDialog.js
+++ b/loleaflet/src/control/Control.LokDialog.js
@@ -409,7 +409,7 @@ L.Control.LokDialog = L.Control.extend({
 		}
 
 		this._map.setWinId(dlgId);
-		if (dlgId in this._dialogs && this._dialogs[dlgId].cursorVisible) {
+		if (dlgId in this._dialogs) {
 			this._map.focus();
 		} else {
 			this._map.blur();
@@ -964,6 +964,8 @@ L.Control.LokDialog = L.Control.extend({
 		if (e.winId === 0) {
 			// We lost the focus.
 			this._onEditorGotFocus();
+		} else {
+			this.focus(e.winId);
 		}
 	},
 
@@ -1027,7 +1029,7 @@ L.Control.LokDialog = L.Control.extend({
 
 			// if dialog is hidden, show it
 			if (container)
-				 $(container).parent().show();
+				$(container).parent().show();
 
 			if (parentId in that._dialogs) {
 				// We might have closed the dialog by the time we render.
@@ -1041,11 +1043,12 @@ L.Control.LokDialog = L.Control.extend({
 
 	// Binary dialog msg recvd from core
 	_onDialogPaint: function (e) {
-		var parentId = this._getParentId(e.id);
+		var id = parseInt(e.id);
+		var parentId = this._getParentId(id);
 		if (parentId) {
 			this._paintDialogChild(parentId, e.img);
 		} else {
-			this._paintDialog(e.id, e.rectangle, e.img);
+			this._paintDialog(id, e.rectangle, e.img);
 		}
 	},
 
commit 7e8914cae97fabb8936be44292c3c7ba002b2588
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Mon Jan 13 23:21:01 2020 -0500
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Jan 28 18:10:14 2020 +0100

    leaflet: change focus on rendering dialogs
    
    Change-Id: I73002acb82950fb6a207f77768956d7cbfcd8a0d

diff --git a/loleaflet/src/control/Control.LokDialog.js b/loleaflet/src/control/Control.LokDialog.js
index 46892becc..13b261e5e 100644
--- a/loleaflet/src/control/Control.LokDialog.js
+++ b/loleaflet/src/control/Control.LokDialog.js
@@ -1032,9 +1032,8 @@ L.Control.LokDialog = L.Control.extend({
 			if (parentId in that._dialogs) {
 				// We might have closed the dialog by the time we render.
 				that._dialogs[parentId].isPainting = false;
-				if (!that._isSidebar(parentId)) {
-					that.focus(parentId);
-				}
+				if (!that._isSidebar(parentId) && !that._isCalcInputBar(parentId))
+					that._map.fire('changefocuswidget', {winId: parentId, dialog: that});
 			}
 		};
 		img.src = imgData;
commit 09c52fef05264b12c456a3f9927b4b4b475a7c76
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Mon Jan 13 15:49:13 2020 -0500
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Jan 28 18:10:14 2020 +0100

    leaflet: improve refocusing the browser
    
    Change-Id: I8b0ca64bcdb04dd05c271b5a5a2b7cf927e62941

diff --git a/loleaflet/src/control/Control.LokDialog.js b/loleaflet/src/control/Control.LokDialog.js
index 84513d46f..46892becc 100644
--- a/loleaflet/src/control/Control.LokDialog.js
+++ b/loleaflet/src/control/Control.LokDialog.js
@@ -349,7 +349,7 @@ L.Control.LokDialog = L.Control.extend({
 			this._dialogs[e.id].cursorVisible = e.visible === 'true';
 			if (this._dialogs[e.id].cursorVisible) {
 				$('#' + strId + '-cursor').css({display: 'block'});
-				this._map.fire('changefocuswidget', {winId: e.id, dialog: this}); // Us.
+				this._map.onFocusDialog(this, e.id);
 			}
 			else {
 				$('#' + strId + '-cursor').css({display: 'none'});
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 2b13de11c..0f69fe74c 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -1373,11 +1373,12 @@ L.Map = L.Evented.extend({
 
 	// Our browser tab got focus.
 	_onGotFocus: function () {
-		if (this._activeDialog) {
-			this._activeDialog.focus(this._winId);
-		} else {
+		if (this._winId === 0) {
 			this.fire('editorgotfocus');
 		}
+		else if (this._activeDialog) {
+			this._activeDialog.focus(this._winId);
+		}
 
 		this._activate();
 	},
commit bcd7af96579181969f1d6c1c977731e030fe3c6e
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sat Jan 25 11:40:19 2020 -0500
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Jan 28 18:10:14 2020 +0100

    leaflet: Impress toolbar fixes for sidebar state
    
    Impress toolbar now reflects the state of the sidebar.
    All sidebars now show correctly for Impress docs,
    except for the properties deck, which conflicts with
    the sidebar button.
    
    Change-Id: I8802e5e35b388df20ca21c4f756b4d95197de570

diff --git a/loleaflet/src/control/Control.Toolbar.js b/loleaflet/src/control/Control.Toolbar.js
index 947a19a3a..8bb1e3e05 100644
--- a/loleaflet/src/control/Control.Toolbar.js
+++ b/loleaflet/src/control/Control.Toolbar.js
@@ -961,10 +961,10 @@ function initNormalToolbar() {
 		{type: 'spacer'},
 		{type: 'button',  id: 'edit',  img: 'edit'},
 		{type: 'button',  id: 'sidebar', img: 'sidebar_modify_page', hint: _UNO('.uno:Sidebar', '', true), uno: '.uno:Sidebar', hidden: true},
-		{type: 'button',  id: 'sidebar-modify-page', img: 'sidebar_modify_page', hint: _UNO('.uno:ModifyPage', 'presentation', true), uno: 'ModifyPage', hidden: true},
-		{type: 'button',  id: 'sidebar-slide-change', img: 'sidebar_slide_change', hint: _UNO('.uno:SlideChangeWindow', 'presentation', true), uno: 'SlideChangeWindow', hidden: true},
-		{type: 'button',  id: 'sidebar-custom-animation', img: 'sidebar_custom_animation', hint: _UNO('.uno:CustomAnimation', 'presentation', true), uno: 'CustomAnimation', hidden: true},
-		{type: 'button',  id: 'sidebar-master-slides', img: 'sidebar_master_slides', hint: _UNO('.uno:MasterSlidesPanel', 'presentation', true), uno: 'MasterSlidesPanel', hidden: true},
+		{type: 'button',  id: 'modifypage', img: 'sidebar_modify_page', hint: _UNO('.uno:ModifyPage', 'presentation', true), uno: '.uno:ModifyPage', hidden: true},
+		{type: 'button',  id: 'slidechangewindow', img: 'sidebar_slide_change', hint: _UNO('.uno:SlideChangeWindow', 'presentation', true), uno: '.uno:SlideChangeWindow', hidden: true},
+		{type: 'button',  id: 'customanimation', img: 'sidebar_custom_animation', hint: _UNO('.uno:CustomAnimation', 'presentation', true), uno: '.uno:CustomAnimation', hidden: true},
+		{type: 'button',  id: 'masterslidespanel', img: 'sidebar_master_slides', hint: _UNO('.uno:MasterSlidesPanel', 'presentation', true), uno: '.uno:MasterSlidesPanel', hidden: true},
 		{type: 'break', id: 'breaksidebar', hidden: true},
 		{type: 'button',  id: 'fold',  img: 'fold', desktop: true, mobile: false, hidden: true},
 		{type: 'button',  id: 'hamburger-tablet',  img: 'hamburger', desktop: false, mobile: false, tablet: true, iosapptablet: false, hidden: true},
@@ -1639,7 +1639,7 @@ function onDocLayerInit() {
 		break;
 	case 'presentation':
 		if (toolbarUp) {
-			toolbarUp.show('breaksidebar', 'sidebar-modify-page');
+			toolbarUp.show('breaksidebar', 'sidebar', 'modifypage');
 		}
 
 		var presentationToolbar = w2ui['presentation-toolbar'];
@@ -1666,7 +1666,7 @@ function onDocLayerInit() {
 		if (toolbarUp)
 			toolbarUp.show('leftpara', 'centerpara', 'rightpara', 'justifypara', 'breakpara', 'linespacing',
 			'breakspacing', 'defaultbullet', 'defaultnumbering', 'breakbullet', 'inserttextbox', 'inserttable', 'backcolor',
-			'breaksidebar', 'sidebar-modify-page', 'sidebar-slide-change', 'sidebar-custom-animation', 'sidebar-master-slides');
+			'breaksidebar', 'sidebar', 'modifypage', 'slidechangewindow', 'customanimation', 'masterslidespanel');
 		if (statusbar)
 			statusbar.show('prev', 'next');
 
commit da0f3a950a03c7ac9544176ca9d2e48e9a0126b8
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sat Jan 18 16:04:26 2020 -0500
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Jan 28 18:10:14 2020 +0100

    wsd: per-user cookies
    
    Cookies may be passed from the client to the storage,
    in which case each user may have its own unique set
    of cookies. These cookies are now preserved in the
    ClientSession, which is per connection, and are then
    passed to the storage to use when communicating with
    the WOPI-like backend.
    
    (cherry picked from commit 6022faf3cc9b622b490c3f8ca91efbff8e542414)
    
    Change-Id: Ic2e13fa541a5ee01b7383939bbbf7d46ea75684b

diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index beed136e5..60ed55c6f 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -60,7 +60,19 @@ ClientSession::ClientSession(const std::string& id,
     _isTextDocument(false)
 {
     const size_t curConnections = ++LOOLWSD::NumConnections;
-    LOG_INF("ClientSession ctor [" << getName() << "], current number of connections: " << curConnections);
+    LOG_INF("ClientSession ctor [" << getName() << "] for URI: [" << _uriPublic.toString()
+                                   << "], current number of connections: " << curConnections);
+
+    for (const auto& param : _uriPublic.getQueryParameters())
+    {
+        if (param.first == "reuse_cookies")
+        {
+            // Cache the cookies to avoid re-parsing the URI again.
+            _cookies = param.second;
+            LOG_INF("ClientSession [" << getName() << "] has cookies: " << _cookies);
+            break;
+        }
+    }
 
     // populate with random values.
     for (auto it : _clipboardKeys)
diff --git a/wsd/ClientSession.hpp b/wsd/ClientSession.hpp
index 8ee184687..d714179ce 100644
--- a/wsd/ClientSession.hpp
+++ b/wsd/ClientSession.hpp
@@ -123,6 +123,8 @@ public:
     /// The access token of this session.
     Authorization getAuthorization() const;
 
+    const std::string& getCookies() const { return _cookies; }
+
     /// Set WOPI fileinfo object
     void setWopiFileInfo(std::unique_ptr<WopiStorage::WOPIFileInfo>& wopiFileInfo) { _wopiFileInfo = std::move(wopiFileInfo); }
 
@@ -220,6 +222,9 @@ private:
     /// URI with which client made request to us
     const Poco::URI _uriPublic;
 
+    /// The cookies we should pass on to the storage on saving.
+    std::string _cookies;
+
     /// Whether this session is the owner of currently opened document
     bool _isDocumentOwner;
 
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 876436abe..1eed16ea0 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -596,8 +596,8 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
     WopiStorage* wopiStorage = dynamic_cast<WopiStorage*>(_storage.get());
     if (wopiStorage != nullptr)
     {
-        std::unique_ptr<WopiStorage::WOPIFileInfo> wopifileinfo =
-            wopiStorage->getWOPIFileInfo(session->getAuthorization(), *_lockCtx);
+        std::unique_ptr<WopiStorage::WOPIFileInfo> wopifileinfo = wopiStorage->getWOPIFileInfo(
+            session->getAuthorization(), session->getCookies(), *_lockCtx);
         userId = wopifileinfo->getUserId();
         username = wopifileinfo->getUsername();
         userExtraInfo = wopifileinfo->getUserExtraInfo();
@@ -754,9 +754,9 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
     if (!_storage->isLoaded())
     {
         std::string localPath = _storage->loadStorageFileToLocal(
-            session->getAuthorization(), *_lockCtx, templateSource);
+            session->getAuthorization(), session->getCookies(), *_lockCtx, templateSource);
 
-        if (!_storage->updateLockState(session->getAuthorization(), *_lockCtx, true))
+        if (!_storage->updateLockState(session->getAuthorization(), session->getCookies(), *_lockCtx, true))
             LOG_ERR("Failed to lock!");
 
 #if !MOBILEAPP
@@ -990,8 +990,8 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId, bool su
     LOG_DBG("Persisting [" << _docKey << "] after saving to URI [" << uriAnonym << "].");
 
     assert(_storage && _tileCache);
-    StorageBase::SaveResult storageSaveResult = _storage->saveLocalFileToStorage(
-        auth, *_lockCtx, saveAsPath, saveAsFilename, isRename);
+    const StorageBase::SaveResult storageSaveResult = _storage->saveLocalFileToStorage(
+        auth, it->second->getCookies(), *_lockCtx, saveAsPath, saveAsFilename, isRename);
     if (storageSaveResult.getResult() == StorageBase::SaveResult::OK)
     {
 #if !MOBILEAPP
@@ -1146,7 +1146,7 @@ void DocumentBroker::refreshLock()
     else
     {
         std::shared_ptr<ClientSession> session = it->second;
-        if (!session || !_storage->updateLockState(session->getAuthorization(), *_lockCtx, true))
+        if (!session || !_storage->updateLockState(session->getAuthorization(), session->getCookies(), *_lockCtx, true))
             LOG_ERR("Failed to refresh lock");
     }
 }
@@ -1418,7 +1418,7 @@ void DocumentBroker::disconnectSessionInternal(const std::string& id)
             if (_markToDestroy && // last session to remove; FIXME: Editable?
                 _lockCtx->_isLocked && _storage)
             {
-                if (!_storage->updateLockState(it->second->getAuthorization(), *_lockCtx, false))
+                if (!_storage->updateLockState(it->second->getAuthorization(), it->second->getCookies(), *_lockCtx, false))
                     LOG_ERR("Failed to unlock!");
             }
 
@@ -1782,7 +1782,6 @@ void DocumentBroker::sendRequestedTiles(const std::shared_ptr<ClientSession>& se
     float tilesOnFlyUpperLimit = 0;
     if (normalizedVisArea.hasSurface() && session->getTileWidthInTwips() != 0 && session->getTileHeightInTwips() != 0)
     {
-
         const int tilesFitOnWidth = std::ceil(normalizedVisArea.getRight() / session->getTileWidthInTwips()) -
                                     std::ceil(normalizedVisArea.getLeft() / session->getTileWidthInTwips()) + 1;
         const int tilesFitOnHeight = std::ceil(normalizedVisArea.getBottom() / session->getTileHeightInTwips()) -
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index ab2ad71c6..f465e0a01 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -300,7 +300,10 @@ std::unique_ptr<LocalStorage::LocalFileInfo> LocalStorage::getLocalFileInfo()
     return std::unique_ptr<LocalStorage::LocalFileInfo>(new LocalFileInfo({"localhost" + std::to_string(LastLocalStorageId), "LocalHost#" + std::to_string(LastLocalStorageId++)}));
 }
 
-std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/, LockContext & /*lockCtx*/, const std::string& /*templateUri*/)
+std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/,
+                                                 const std::string& /*cookies*/,
+                                                 LockContext& /*lockCtx*/,
+                                                 const std::string& /*templateUri*/)
 {
 #if !MOBILEAPP
     // /chroot/jailId/user/doc/childId/file.ext
@@ -363,7 +366,10 @@ std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/,
 
 }
 
-StorageBase::SaveResult LocalStorage::saveLocalFileToStorage(const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*saveAsPath*/, const std::string& /*saveAsFilename*/, bool /*isRename*/)
+StorageBase::SaveResult
+LocalStorage::saveLocalFileToStorage(const Authorization& /*auth*/, const std::string& /*cookies*/,
+                                     LockContext& /*lockCtx*/, const std::string& /*saveAsPath*/,
+                                     const std::string& /*saveAsFilename*/, bool /*isRename*/)
 {
     try
     {
@@ -428,6 +434,8 @@ static void addStorageReuseCookie(Poco::Net::HTTPRequest& request, const std::st
     if (!reuseStorageCookies.empty())
     {
         Poco::Net::NameValueCollection nvcCookies;
+        request.getCookies(nvcCookies); // Preserve existing cookies.
+
         std::vector<std::string> cookies = LOOLProtocol::tokenize(reuseStorageCookies, ':');
         for (auto cookie : cookies)
         {
@@ -435,9 +443,10 @@ static void addStorageReuseCookie(Poco::Net::HTTPRequest& request, const std::st
             if (cookieTokens.size() == 2)
             {
                 nvcCookies.add(cookieTokens[0], cookieTokens[1]);
-                LOG_DBG("Added storage reuse cookie [" << cookieTokens[0] << "=" << cookieTokens[1] << "].");
+                LOG_DBG("Added storage reuse cookie [" << cookieTokens[0] << '=' << cookieTokens[1] << "].");
             }
         }
+
         request.setCookies(nvcCookies);
     }
 }
@@ -494,7 +503,9 @@ void LockContext::dumpState(std::ostream& os) const
 
 #if !MOBILEAPP
 
-std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Authorization& auth, LockContext &lockCtx)
+std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Authorization& auth,
+                                                                        const std::string& cookies,
+                                                                        LockContext& lockCtx)
 {
     // update the access_token to the one matching to the session
     Poco::URI uriObject(getUri());
@@ -513,7 +524,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
         auth.authorizeRequest(request);
         addStorageDebugCookie(request);
         if (_reuseCookies)
-            addStorageReuseCookie(request, params["reuse_cookies"]);
+            addStorageReuseCookie(request, cookies);
         addWopiProof(request, params["access_token"]);
         const auto startTime = std::chrono::steady_clock::now();
 
@@ -712,7 +723,8 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
          userCanRename, callDuration}));
 }
 
-bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock)
+bool WopiStorage::updateLockState(const Authorization& auth, const std::string& cookies,
+                                  LockContext& lockCtx, bool lock)
 {
     if (!lockCtx._supportsLocks)
         return true;
@@ -743,7 +755,7 @@ bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCt
             request.set("X-LOOL-WOPI-ExtendedData", getExtendedData());
         addStorageDebugCookie(request);
         if (_reuseCookies)
-            addStorageReuseCookie(request, params["reuse_cookies"]);
+            addStorageReuseCookie(request, cookies);
         addWopiProof(request, params["access_token"]);
 
         psession->sendRequest(request);
@@ -782,7 +794,10 @@ bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCt
 }
 
 /// uri format: http://server/<...>/wopi*/files/<id>/content
-std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockContext &/* lockCtx */, const std::string& templateUri)
+std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth,
+                                                const std::string& cookies,
+                                                LockContext& /*lockCtx*/,
+                                                const std::string& templateUri)
 {
     // WOPI URI to download files ends in '/contents'.
     // Add it here to get the payload instead of file info.
@@ -819,7 +834,7 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockC
         auth.authorizeRequest(request);
         addStorageDebugCookie(request);
         if (_reuseCookies)
-            addStorageReuseCookie(request, params["reuse_cookies"]);
+            addStorageReuseCookie(request, cookies);
         addWopiProof(request, params["access_token"]);
         psession->sendRequest(request);
 
@@ -876,7 +891,10 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockC
     return "";
 }
 
-StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename)
+StorageBase::SaveResult
+WopiStorage::saveLocalFileToStorage(const Authorization& auth, const std::string& cookies,
+                                    LockContext& lockCtx, const std::string& saveAsPath,
+                                    const std::string& saveAsFilename, const bool isRename)
 {
     // TODO: Check if this URI has write permission (canWrite = true)
 
@@ -975,7 +993,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
         request.setContentLength(size);
         addStorageDebugCookie(request);
         if (_reuseCookies)
-            addStorageReuseCookie(request, params["reuse_cookies"]);
+            addStorageReuseCookie(request, cookies);
         addWopiProof(request, params["access_token"]);
         std::ostream& os = psession->sendRequest(request);
 
@@ -1106,17 +1124,20 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
     return saveResult;
 }
 
-std::string WebDAVStorage::loadStorageFileToLocal(
-    const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*templateUri*/)
+std::string WebDAVStorage::loadStorageFileToLocal(const Authorization& /*auth*/,
+                                                  const std::string& /*cookies*/,
+                                                  LockContext& /*lockCtx*/,
+                                                  const std::string& /*templateUri*/)
 {
     // TODO: implement webdav GET.
     setLoaded(true);
     return getUri().toString();
 }
 
-StorageBase::SaveResult WebDAVStorage::saveLocalFileToStorage(
-    const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*saveAsPath*/,
-    const std::string& /*saveAsFilename*/, bool /*isRename*/)
+StorageBase::SaveResult
+WebDAVStorage::saveLocalFileToStorage(const Authorization& /*auth*/, const std::string& /*cookies*/,
+                                      LockContext& /*lockCtx*/, const std::string& /*saveAsPath*/,
+                                      const std::string& /*saveAsFilename*/, bool /*isRename*/)
 {
     // TODO: implement webdav PUT.
     return StorageBase::SaveResult(StorageBase::SaveResult::OK);
diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp
index 7060cd7a4..bb678ac8a 100644
--- a/wsd/Storage.hpp
+++ b/wsd/Storage.hpp
@@ -53,7 +53,6 @@ struct LockContext
 class StorageBase
 {
 public:
-
     /// Represents basic file's attributes.
     /// Used for local and network files.
     class FileInfo
@@ -217,15 +216,25 @@ public:
     std::string getFileExtension() const { return Poco::Path(_fileInfo.getFilename()).getExtension(); }
 
     /// Update the locking state (check-in/out) of the associated file
-    virtual bool updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock) = 0;
+    virtual bool updateLockState(const Authorization& auth, const std::string& cookies,
+                                 LockContext& lockCtx, bool lock)
+        = 0;
 
     /// Returns a local file path for the given URI.
     /// If necessary copies the file locally first.
-    virtual std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) = 0;
+    virtual std::string loadStorageFileToLocal(const Authorization& auth,
+                                               const std::string& /*cookies*/, LockContext& lockCtx,
+                                               const std::string& templateUri)
+        = 0;
 
     /// Writes the contents of the file back to the source.
+    /// @param cookies A string representing key=value pairs that are set as cookies.
     /// @param savedFile When the operation was saveAs, this is the path to the file that was saved.
-    virtual SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) = 0;
+    virtual SaveResult
+    saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/,
+                           LockContext& lockCtx, const std::string& saveAsPath,
+                           const std::string& saveAsFilename, const bool isRename)
+        = 0;
 
     static size_t getFileSize(const std::string& filename);
 
@@ -312,11 +321,19 @@ public:
     /// obtained using getFileInfo method
     std::unique_ptr<LocalFileInfo> getLocalFileInfo();
 
-    bool updateLockState(const Authorization &, LockContext &, bool) override { return true; }
+    bool updateLockState(const Authorization&, const std::string&, LockContext&, bool) override
+    {
+        return true;
+    }
 
-    std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override;
+    std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/,
+                                       LockContext& lockCtx,
+                                       const std::string& templateUri) override;
 
-    SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override;
+    SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/,
+                                      LockContext& lockCtx, const std::string& saveAsPath,
+                                      const std::string& saveAsFilename,
+                                      const bool isRename) override;
 
 private:
     /// True if the jailed file is not linked but copied.
@@ -545,15 +562,21 @@ public:
     /// which can then be obtained using getFileInfo()
     /// Also sets up the locking context for future operations.
     std::unique_ptr<WOPIFileInfo> getWOPIFileInfo(const Authorization& auth,
-                                                  LockContext &lockCtx);
+                                                  const std::string& cookies, LockContext& lockCtx);
 
     /// Update the locking state (check-in/out) of the associated file
-    bool updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock) override;
+    bool updateLockState(const Authorization& auth, const std::string& cookies,
+                         LockContext& lockCtx, bool lock) override;
 
     /// uri format: http://server/<...>/wopi*/files/<id>/content
-    std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override;
+    std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/,
+                                       LockContext& lockCtx,
+                                       const std::string& templateUri) override;
 
-    SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override;
+    SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/,
+                                      LockContext& lockCtx, const std::string& saveAsPath,
+                                      const std::string& saveAsFilename,
+                                      const bool isRename) override;
 
     /// Total time taken for making WOPI calls during load
     std::chrono::duration<double> getWopiLoadDuration() const { return _wopiLoadDuration; }
@@ -585,11 +608,19 @@ public:
     // Implement me
     // WebDAVFileInfo getWebDAVFileInfo(const Poco::URI& uriPublic);
 
-    bool updateLockState(const Authorization &, LockContext &, bool) override { return true; }
+    bool updateLockState(const Authorization&, const std::string&, LockContext&, bool) override
+    {
+        return true;
+    }
 
-    std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override;
+    std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/,
+                                       LockContext& lockCtx,
+                                       const std::string& templateUri) override;
 
-    SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override;
+    SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/,
+                                      LockContext& lockCtx, const std::string& saveAsPath,
+                                      const std::string& saveAsFilename,
+                                      const bool isRename) override;
 
 private:
     std::unique_ptr<AuthBase> _authAgent;


More information about the Libreoffice-commits mailing list