[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-1-9' - 10 commits - loleaflet/dist loleaflet/reference.html loleaflet/src loolwsd/DocumentBroker.cpp loolwsd/protocol.txt loolwsd/Storage.cpp loolwsd/Storage.hpp

Pranav Kant pranavk at collabora.co.uk
Thu Nov 10 21:58:22 UTC 2016


 loleaflet/dist/toolbar/toolbar.js         |    4 
 loleaflet/reference.html                  |  146 +++++++++++++++++++++++++++---
 loleaflet/src/control/Control.Menubar.js  |   33 +++++-
 loleaflet/src/control/Toolbar.js          |   14 ++
 loleaflet/src/core/Socket.js              |   10 +-
 loleaflet/src/layer/tile/TileLayer.js     |    8 +
 loleaflet/src/map/handler/Map.Keyboard.js |    2 
 loleaflet/src/map/handler/Map.Print.js    |    4 
 loleaflet/src/map/handler/Map.WOPI.js     |   36 ++++++-
 loolwsd/DocumentBroker.cpp                |   15 ++-
 loolwsd/Storage.cpp                       |   15 ++-
 loolwsd/Storage.hpp                       |   12 ++
 loolwsd/protocol.txt                      |    7 +
 13 files changed, 275 insertions(+), 31 deletions(-)

New commits:
commit 9d798cd6f4f0f37156dc9c22e87de82fbbdd4c6f
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 23:06:15 2016 +0530

    tdf#103671: 'true' -> true
    
    Treat booleans as booleans, not string
    
    Change-Id: Id0d3bee44b42461671379754e64e5e2f9b318045
    (cherry picked from commit dacf16f2d85d2fb5a4de8da52ce64b6409a7dbcd)

diff --git a/loolwsd/Storage.cpp b/loolwsd/Storage.cpp
index dcaa0a7..c58b1bf 100644
--- a/loolwsd/Storage.cpp
+++ b/loolwsd/Storage.cpp
@@ -346,17 +346,17 @@ WopiStorage::WOPIFileInfo WopiStorage::getWOPIFileInfo(const Poco::URI& uriPubli
         const auto userNameVar = getOrWarn(object,"UserFriendlyName");
         userName = (userNameVar.isString() ? userNameVar.toString() : "anonymous");
         const auto canWriteVar = getOrWarn(object, "UserCanWrite");
-        canWrite = canWriteVar.isString() ? (canWriteVar.toString() == "true") : false;
+        canWrite = canWriteVar.isBoolean() ? canWriteVar.convert<bool>() : false;
         const auto postMessageOriginVar = getOrWarn(object, "PostMessageOrigin");
         postMessageOrigin = postMessageOriginVar.isString() ? postMessageOriginVar.toString() : "";
         const auto hidePrintOptionVar = getOrWarn(object, "HidePrintOption");
-        hidePrintOption = hidePrintOptionVar.isString() ? (hidePrintOptionVar.toString() == "true") : false;
+        hidePrintOption = hidePrintOptionVar.isBoolean() ? hidePrintOptionVar.convert<bool>() : false;
         const auto hideSaveOptionVar = getOrWarn(object, "HideSaveOption");
-        hideSaveOption = hideSaveOptionVar.isString() ? (hideSaveOptionVar.toString() == "true") : false;
+        hideSaveOption = hideSaveOptionVar.isBoolean() ? hideSaveOptionVar.convert<bool>() : false;
         const auto hideExportOptionVar = getOrWarn(object, "HideExportOption");
-        hideExportOption = hideExportOptionVar.isString() ? (hideExportOptionVar.toString() == "true") : false;
+        hideExportOption = hideExportOptionVar.isBoolean() ? hideExportOptionVar.convert<bool>() : false;
         const auto enableOwnerTerminationVar = getOrWarn(object, "EnableOwnerTermination");
-        enableOwnerTermination = enableOwnerTerminationVar.isString() ? (enableOwnerTerminationVar.toString() == "true") : false;
+        enableOwnerTermination = enableOwnerTerminationVar.isBoolean() ? enableOwnerTerminationVar.convert<bool>() : false;
     }
     else
         Log::error("WOPI::CheckFileInfo is missing JSON payload");
commit b74e4d65ef431da6727a136b63f644a3e103fee8
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 22:25:31 2016 +0530

    More documentation about post message API
    
    Change-Id: I362e159c32d2ea93139be58ca647a2f4c5678dee
    (cherry picked from commit d060b242e8274d194b1a2ccf15d3a9ee39525704)

diff --git a/loleaflet/reference.html b/loleaflet/reference.html
index 11ccb80..529728a 100644
--- a/loleaflet/reference.html
+++ b/loleaflet/reference.html
@@ -70,6 +70,7 @@
 		<h4 style="color:red;">PostMessage API</h4>
 		<ul>
 		        <li><a href="#loleaflet-postmessage-initialization">Initialization</a></li>
+			<li><a href="#loleaflet-postmessage-query">Query API</a></li>
 			<li><a href="#loleaflet-postmessage-sessions">Session Management</a></li>
 			<li><a href="#loleaflet-postmessage-actions">Actions</a></li>
 		</ul>
@@ -2733,13 +2734,13 @@ The <code>id</code> property of ErrorEvent can have the following values:
 
 <h2 id="loleaflet-postmessage">PostMessage API</h2>
 
-<p>PostMessage API is used to post messages to outer frame when loleaflet is
-  enclosed in a parent frame. This is useful for hosts wanting to
-  integrate LibreOffice Online in it.</p>
+<p>PostMessage API is used to interact with parent frame when loleaflet is
+  enclosed in one. This is useful for hosts wanting to
+  integrate LibreOffice Online in them.</p>
 
 <p>This API is mostly based
   on <a href="https://wopi.readthedocs.io/en/latest/scenarios/postmessage.html">WOPI
-    specification</a> with few additions/modifications. All messages sent are
+    specification</a> with few extensions/modifications. All messages sent are
   in this form</p>
 
 <pre><code class="javascript">
@@ -2754,9 +2755,12 @@ The <code>id</code> property of ErrorEvent can have the following values:
 
 SendTime is the timestamp returned by browsers' Date.now()
 
+<br/><br/>
+Similarly, message received should be in same form.
+
 <h3 id="loleaflet-postmessage-initialization">Initialization</h3>
 Editor to WOPI host
-<table data-id='postmessage-initialization'>
+<table data-id='postmessage-initialization-from-editor'>
 	<tr>
 		<th>MessageId</th>
 		<th>Values</th>
@@ -2773,10 +2777,30 @@ Editor to WOPI host
 		ready/loaded.</td>
 	</tr>
 </table>
+WOPI host to editor
+<table data-id='postmessage-initialization-to-editor'>
+	<tr>
+		<th>MessageId</th>
+		<th>Values</th>
+		<th>Description</th>
+	</tr>
+	<tr>
+		<td><code><b>Host_PostMessageReady</b></code></td>
+		<td><code>
+		</code></td>
+		<td>
+		  See WOPI docs for detail.
+		</td>
+	</tr>
+</table>
 
-<h3 id="loleaflet-postmessage-sessions">Session Management</h3>
+<h3 id="loleaflet-postmessage-query">Query</h3>
+You can query data from the editor using post message API. All responses are
+returned with query's MessageId suffixed with '_Resp' as shown below
+<br/><br/>
+Getters<br/>
 WOPI Host to Editor
-<table data-id='postmessage-sessions'>
+<table data-id='postmessage-query-getters'>
 	<tr>
 		<th>MessageId</th>
 		<th>Values</th>
@@ -2790,8 +2814,52 @@ WOPI Host to Editor
 		Queries the editor for currently active views of the document. Response is returned in form of <code>Get_Views_Resp</code>
 		</td>
 	</tr>
+	<tr>
+		<td><code><b>Get_Export_Formats</b></code></td>
+		<td><code>
+		</code></td>
+		<td>
+		Queries the editor for all the supported export formats for currently opened document.
+		</td>
+	</tr>
+
+</table>
+Getters response<br/>
+Editor to WOPI host
+<table data-id='postmessage-query-getters-resp'>
+	<tr>
+		<th>MessageId</th>
+		<th>Values</th>
+		<th>Description</th>
+	</tr>
+	<tr>
+		<td><code><b>Get_Views_Resp</b></code></td>
+		<td><code>
+		    <nobr>ViewId: <Number></nobr>
+		    <nobr>UserId: <String></nobr>
+		    <nobr>UserName: <String></nobr>
+		    <nobr>Color: <Number></nobr>
+		</code></td>
+		<td>Give details of all current views when queried using <code>Get_Views</code>
+		</td>
+	</tr>
+	<tr>
+		<td><code><b>Get_Export_Formats_Resp</b></code></td>
+		<td><code>
+		    <nobr>Label: <String></nobr>
+		    <nobr>Format: <String></nobr>
+		</code></td>
+		<td>
+		Response to query <code>Get_Export_Formats</code>.
+		Label would contain a localised string explaining about the format.
+		Format is the file extension of the format which is required while requesting
+		export of the document.
+		</td>
+	</tr>
+
 </table>
 
+<h3 id="loleaflet-postmessage-sessions">Session Management</h3>
 Editor to WOPI Host
 <table data-id='postmessage-sessions'>
 	<tr>
@@ -2821,18 +2889,7 @@ Editor to WOPI Host
 		<td>View with <code>ViewId</code> has closed the document.
 		</td>
 	</tr>
-	<tr>
-		<td><code><b>Get_Views_Resp</b></code></td>
-		<td><code>
-		    <nobr>ViewId: <Number></nobr>
-		    <nobr>UserId: <String></nobr>
-		    <nobr>UserName: <String></nobr>
-		    <nobr>Color: <Number></nobr>
-		</code></td>
-		<td>Give details of all current views when queried using <code>Get_Views</code>
-		</td>
-	</tr>
-</table>
+	</table>
 
 <h3 id="loleaflet-postmessage-actions">Actions</h3>
 WOPI host to editor
@@ -2848,11 +2905,12 @@ WOPI host to editor
 		    <nobr>DontTerminateEdit: <boolean></nobr>
 		    <nobr>DontSaveIfUnmodified: <boolean></nobr>
 		</code></td>
-		<td>Saves the document. DontTerminateEdit is relevant for spreadsheets where saving
+		<td>Saves the document.<br/>
+		<code>DontTerminateEdit</code> is relevant for spreadsheets where saving
 		a document can terminate the edit mode (text cursor dissappearing). Setting this to
 		true won't terminate the edit mode and can be used to save document without disrupting
-		user's editing session in spreadsheets.
-		DontSaveIfUnmodified prevents loolwsd to save the file back to storage if document is
+		user's editing session in spreadsheets.<br/>
+		<code>DontSaveIfUnmodified</code> prevents loolwsd to save the file back to storage if document is
 		unmodified (only cursor position changed etc.) but still saved. This can be helpful
 		to prevent creating unnecessary file revisions.
 		</td>
@@ -2871,7 +2929,8 @@ WOPI host to editor
 		    <nobr>Format: <String></nobr>
 		</code></td>
 		<td>
-		Downloads the document in format specified by <code>Format</code>.
+		Downloads the document in format specified by <code>Format</code>. Format must be from the list returned
+		in <code>Get_Export_Formats</code>
 		</td>
 	</tr>
 </table>
commit 5d37fb02716a7cc7f39fef5d425745a13321c358
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 22:00:46 2016 +0530

    loleaflet: Fix browser print
    
    Accessing the parent iframe, atleast on my local box, where
    parent frame and loleaflet frame have different origin, is not
    allowed by browser security policy.
    
    Change-Id: Ia3a356fa1d8a81f38bbc27d256471302be8b6729
    (cherry picked from commit 08a365302ec763fab2e0092bc4b786fe3ca9ee54)

diff --git a/loleaflet/src/map/handler/Map.Print.js b/loleaflet/src/map/handler/Map.Print.js
index 9a9743f..c2f8265 100644
--- a/loleaflet/src/map/handler/Map.Print.js
+++ b/loleaflet/src/map/handler/Map.Print.js
@@ -36,8 +36,8 @@ L.Map.Print = L.Handler.extend({
 
 	_onInitPrint: function (e) {
 		var blob = new Blob([e.response], {type: 'application/pdf'});
-		var url = parent.URL.createObjectURL(blob);
-		this._printIframe = L.DomUtil.create('iframe', '', parent.document.body);
+		var url = URL.createObjectURL(blob);
+		this._printIframe = L.DomUtil.create('iframe', '', document.body);
 		this._printIframe.onload = L.bind(this._onIframeLoaded, this);
 		L.DomUtil.setStyle(this._printIframe, 'visibility', 'hidden');
 		L.DomUtil.setStyle(this._printIframe, 'position', 'fixed');
commit c57e767340f870b89ea63808d2616a521e73a748
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 21:03:18 2016 +0530

    tdf#103641: Another Post message API - Get_Export_Formats
    
    Change-Id: I8a502d3c88c83cc7fb6c3113522ed637bf349a0e
    (cherry picked from commit e850ac836f566316d827a42e22e6bbe35f2c11e7)

diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index 1854bd2..ed71363 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -469,8 +469,17 @@ L.Control.Menubar = L.Control.extend({
 			if (menu[i].id === 'save' && this._map['wopi'].HideSaveOption)
 				continue;
 
-			if (menu[i].id === 'downloadas' && this._map['wopi'].HideExportOption)
-				continue;
+			// Keep track of all 'downloadas-' options and register them as
+			// export formats with docLayer which can then be publicly accessed unlike
+			// this Menubar control for which there doesn't seem to be any easy way
+			// to get access to.
+			if (menu[i].id && menu[i].id.startsWith('downloadas-')) {
+				var format = menu[i].id.substring('downloadas-'.length);
+				this._map._docLayer.registerExportFormat(menu[i].name, format);
+
+				if (this._map['wopi'].HideExportOption)
+					continue;
+			}
 
 			var liItem = L.DomUtil.create('li', '');
 			var aItem = L.DomUtil.create('a', '', liItem);
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 74cb6e2..c167b28 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -240,6 +240,14 @@ L.TileLayer = L.GridLayer.extend({
 		return events;
 	},
 
+	registerExportFormat: function(label, format) {
+		if (!this._exportFormats) {
+			this._exportFormats = [];
+		}
+
+		this._exportFormats.push({label: label, format: format});
+	},
+
 	setUrl: function (url, noRedraw) {
 		this._url = url;
 
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index f144509..1281baf 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -64,6 +64,17 @@ L.Map.WOPI = L.Handler.extend({
 				this._map.downloadAs(filename + '.' + format, format);
 			}
 		}
+		else if (msg.MessageId === 'Get_Export_Formats') {
+			var exportFormatsResp = [];
+			for (var idx in this._map._docLayer._exportFormats) {
+				exportFormatsResp.push({
+					Label: this._map._docLayer._exportFormats[idx].label,
+					Format: this._map._docLayer._exportFormats[idx].format
+				});
+			}
+
+			this._postMessage({msgId: 'Get_Export_Formats_Resp', args: exportFormatsResp});
+		}
 	},
 
 	_postMessage: function(e) {
commit 80186c16d3ef14180c64061c3bd8b6e291e05237
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 18:15:22 2016 +0530

    tdf#103641: WOPI: Implement Action_Save, Action_Print, Action_Export
    
    WOPI hosts can now send above mentioned messages to loleaflet so
    that loleaflet does stuff accordingly.
    
    Change-Id: I50e10a62c5b629bd12f7d9ce51bcd13cb13cdd8a
    (cherry picked from commit 5219baaab0691fa6d727d966d0376b75061331f6)

diff --git a/loleaflet/reference.html b/loleaflet/reference.html
index a07378f..11ccb80 100644
--- a/loleaflet/reference.html
+++ b/loleaflet/reference.html
@@ -71,6 +71,7 @@
 		<ul>
 		        <li><a href="#loleaflet-postmessage-initialization">Initialization</a></li>
 			<li><a href="#loleaflet-postmessage-sessions">Session Management</a></li>
+			<li><a href="#loleaflet-postmessage-actions">Actions</a></li>
 		</ul>
 		<h4>UI Layers</h4>
 		<ul>
@@ -2754,7 +2755,7 @@ The <code>id</code> property of ErrorEvent can have the following values:
 SendTime is the timestamp returned by browsers' Date.now()
 
 <h3 id="loleaflet-postmessage-initialization">Initialization</h3>
-
+Editor to WOPI host
 <table data-id='postmessage-initialization'>
 	<tr>
 		<th>MessageId</th>
@@ -2774,7 +2775,24 @@ SendTime is the timestamp returned by browsers' Date.now()
 </table>
 
 <h3 id="loleaflet-postmessage-sessions">Session Management</h3>
+WOPI Host to Editor
+<table data-id='postmessage-sessions'>
+	<tr>
+		<th>MessageId</th>
+		<th>Values</th>
+		<th>Description</th>
+	</tr>
+	<tr>
+		<td><code><b>Get_Views</b></code></td>
+		<td><code>
+		</code></td>
+		<td>
+		Queries the editor for currently active views of the document. Response is returned in form of <code>Get_Views_Resp</code>
+		</td>
+	</tr>
+</table>
 
+Editor to WOPI Host
 <table data-id='postmessage-sessions'>
 	<tr>
 		<th>MessageId</th>
@@ -2816,6 +2834,49 @@ SendTime is the timestamp returned by browsers' Date.now()
 	</tr>
 </table>
 
+<h3 id="loleaflet-postmessage-actions">Actions</h3>
+WOPI host to editor
+<table data-id='postmessage-actions'>
+	<tr>
+		<th>MessageId</th>
+		<th>Values</th>
+		<th>Description</th>
+	</tr>
+	<tr>
+		<td><code><b>Action_Save</b></code></td>
+		<td><code>
+		    <nobr>DontTerminateEdit: <boolean></nobr>
+		    <nobr>DontSaveIfUnmodified: <boolean></nobr>
+		</code></td>
+		<td>Saves the document. DontTerminateEdit is relevant for spreadsheets where saving
+		a document can terminate the edit mode (text cursor dissappearing). Setting this to
+		true won't terminate the edit mode and can be used to save document without disrupting
+		user's editing session in spreadsheets.
+		DontSaveIfUnmodified prevents loolwsd to save the file back to storage if document is
+		unmodified (only cursor position changed etc.) but still saved. This can be helpful
+		to prevent creating unnecessary file revisions.
+		</td>
+	</tr>
+	<tr>
+		<td><code><b>Action_Print</b></code></td>
+		<td><code>
+		</code></td>
+		<td>
+		Prints the document.
+		</td>
+	</tr>
+	<tr>
+		<td><code><b>Action_Export</b></code></td>
+		<td><code>
+		    <nobr>Format: <String></nobr>
+		</code></td>
+		<td>
+		Downloads the document in format specified by <code>Format</code>.
+		</td>
+	</tr>
+</table>
+
+
 <h2 id="marker">Marker</h2>
 
 <p>Used to put markers on the map. Extends <a href="#layer">Layer</a>.</p>
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index a8f061e..f144509 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -2,6 +2,7 @@
  * L.WOPI contains WOPI related logic
  */
 
+/* global title */
 L.Map.WOPI = L.Handler.extend({
 
 	PostMessageOrigin: false,
@@ -46,6 +47,23 @@ L.Map.WOPI = L.Handler.extend({
 		else if (msg.MessageId === 'Close_Session') {
 			this._map._socket.sendMessage('closedocument');
 		}
+		else if (msg.MessageId === 'Action_Save') {
+			var dontTerminateEdit = e.Values && e.Values['DontTerminateEdit'];
+			var dontSaveIfUnmodified = e.Values && e.Values['DontSaveIfUnmodified'];
+
+			this._map.save(dontTerminateEdit, dontSaveIfUnmodified);
+		}
+		else if (msg.MessageId === 'Action_Print') {
+			this._map.print();
+		}
+		else if (msg.MessageId === 'Action_Export') {
+			if (msg.Values) {
+				var format = msg.Values.Format;
+				var filename = title.substr(0, title.lastIndexOf('.')) || title;
+				filename = filename === '' ? 'document' : filename;
+				this._map.downloadAs(filename + '.' + format, format);
+			}
+		}
 	},
 
 	_postMessage: function(e) {
commit 2756b4aa6846e5f7423bf9e4b921aafbbdf546ff
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 18:12:46 2016 +0530

    loleaflet: Factor out save uno command
    
    Change-Id: I155329f9dfa37cb47cbac34aa885b3d7a0cbb573
    (cherry picked from commit 9bfd5a512ed64fc705de118422a1319fa438cfb0)

diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js
index 19eeaa9..3de887f 100644
--- a/loleaflet/src/control/Toolbar.js
+++ b/loleaflet/src/control/Toolbar.js
@@ -119,6 +119,20 @@ L.Map.include({
 		}
 	},
 
+	save: function(dontTerminateEdit, dontSaveIfUnmodified) {
+		var args = {
+			DontTerminateEdit: {
+				type: 'boolean',
+				value: !!dontTerminateEdit
+			},
+			DontSaveIfUnmodified: {
+				type: 'boolean',
+				value: !!dontSaveIfUnmodified
+			}
+		};
+		this.sendUnoCommand('.uno:Save', args);
+	},
+
 	sendUnoCommand: function (command, json) {
 		if (this._permission === 'edit') {
 			this._socket.sendMessage('uno ' + command + (json ? ' ' + JSON.stringify(json) : ''));
diff --git a/loleaflet/src/map/handler/Map.Keyboard.js b/loleaflet/src/map/handler/Map.Keyboard.js
index b441534..6e64ae4 100644
--- a/loleaflet/src/map/handler/Map.Keyboard.js
+++ b/loleaflet/src/map/handler/Map.Keyboard.js
@@ -430,7 +430,7 @@ L.Map.Keyboard = L.Handler.extend({
 			this._map.print();
 			return true;
 		case 83: // s
-			this._map._socket.sendMessage('uno .uno:Save {\"DontTerminateEdit\":{\"type\":\"boolean\",\"value\":true}, \"DontSaveIfUnmodified\":{\"type\":\"boolean\",\"value\":true}}');
+			this._map.save(true, true);
 			return true;
 		case 86: // v
 		case 118: // v (Safari)
commit d6991b67886816c03102a42a709c13b2df7f97e5
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 17:51:39 2016 +0530

    tdf#103641: Implement ability to hide save, print, export options
    
    Add more WOPI extensions for this - HidePrintOption,
    HideSaveOption, HideExportOption. Setting HideExportOption to
    'true' in WOPI CheckFileInfo response would hide the 'Download
    as' option from the File menu.
    
    Change-Id: Ia2259ee9525cc6c4331a52e2221af4df188eab07
    (cherry picked from commit 2168617d603a81eab62465a9b18d6f64b35e66da)

diff --git a/loleaflet/dist/toolbar/toolbar.js b/loleaflet/dist/toolbar/toolbar.js
index fd3b3e7..970537f 100644
--- a/loleaflet/dist/toolbar/toolbar.js
+++ b/loleaflet/dist/toolbar/toolbar.js
@@ -735,6 +735,10 @@ map.on('doclayerinit', function () {
 		}
 	}
 
+	if (map['wopi'].HideSaveOption) {
+		toolbar.hide('save');
+	}
+
 	var statusbar = w2ui['toolbar-down'];
 	switch (docType) {
 	case 'spreadsheet':
diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index 7eadfac..1854bd2 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -463,6 +463,15 @@ L.Control.Menubar = L.Control.extend({
 				continue;
 			}
 
+			if (menu[i].id === 'print' && this._map['wopi'].HidePrintOption)
+				continue;
+
+			if (menu[i].id === 'save' && this._map['wopi'].HideSaveOption)
+				continue;
+
+			if (menu[i].id === 'downloadas' && this._map['wopi'].HideExportOption)
+				continue;
+
 			var liItem = L.DomUtil.create('li', '');
 			var aItem = L.DomUtil.create('a', '', liItem);
 			aItem.innerHTML = menu[i].name;
@@ -470,6 +479,9 @@ L.Control.Menubar = L.Control.extend({
 			if (menu[i].type === 'menu') {
 				var ulItem = L.DomUtil.create('ul', '', liItem);
 				var subitemList = this._createMenu(menu[i].menu);
+				if (!subitemList.length) {
+					continue;
+				}
 				for (var j in subitemList) {
 					ulItem.appendChild(subitemList[j]);
 				}
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 77d643b..d504ba6 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -188,6 +188,10 @@ L.Socket = L.Class.extend({
 				this._map.fire('postMessage', {msgId: 'App_LoadingStatus', args: {'DocumentLoadedTime': this._map['wopi'].DocumentLoadedTime}});
 			}
 
+			this._map['wopi'].HidePrintOption = !!wopiInfo['HidePrintOption'];
+			this._map['wopi'].HideSaveOption = !!wopiInfo['HideSaveOption'];
+			this._map['wopi'].HideExportOption = !!wopiInfo['HideExportOption'];
+
 			return;
 		}
 		else if (textMsg.startsWith('close: ')) {
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index 8bac050..a8f061e 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -6,6 +6,9 @@ L.Map.WOPI = L.Handler.extend({
 
 	PostMessageOrigin: false,
 	DocumentLoadedTime: false,
+	HidePrintOption: false,
+	HideSaveOption: false,
+	HideExportOption: false,
 
 	initialize: function(map) {
 		this._map = map;
diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp
index 179b2e5..4a79836 100644
--- a/loolwsd/DocumentBroker.cpp
+++ b/loolwsd/DocumentBroker.cpp
@@ -239,17 +239,21 @@ bool DocumentBroker::load(std::shared_ptr<ClientSession>& session, const std::st
             session->setReadOnly();
         }
 
+        // Construct a JSON containing relevant WOPI host properties
+        Object::Ptr wopiInfo = new Object();
         if (!wopifileinfo._postMessageOrigin.empty())
         {
-            // Construct a JSON containing relevant WOPI host properties
-            Object::Ptr wopiInfo = new Object();
             wopiInfo->set("PostMessageOrigin", wopifileinfo._postMessageOrigin);
-            std::ostringstream ossWopiInfo;
-            wopiInfo->stringify(ossWopiInfo);
-
-            session->sendTextFrame("wopi: " + ossWopiInfo.str());
         }
 
+        wopiInfo->set("HidePrintOption", wopifileinfo._hidePrintOption);
+        wopiInfo->set("HideSaveOption", wopifileinfo._hideSaveOption);
+        wopiInfo->set("HideExportOption", wopifileinfo._hideExportOption);
+
+        std::ostringstream ossWopiInfo;
+        wopiInfo->stringify(ossWopiInfo);
+        session->sendTextFrame("wopi: " + ossWopiInfo.str());
+
         // Mark the session as 'Document owner' if WOPI hosts supports it
         if (wopifileinfo._enableOwnerTermination && userid == _storage->getFileInfo()._ownerId)
         {
diff --git a/loolwsd/Storage.cpp b/loolwsd/Storage.cpp
index 0a451ae..dcaa0a7 100644
--- a/loolwsd/Storage.cpp
+++ b/loolwsd/Storage.cpp
@@ -320,6 +320,9 @@ WopiStorage::WOPIFileInfo WopiStorage::getWOPIFileInfo(const Poco::URI& uriPubli
     bool canWrite = false;
     bool enableOwnerTermination = false;
     std::string postMessageOrigin;
+    bool hidePrintOption = false;
+    bool hideSaveOption = false;
+    bool hideExportOption = false;
     std::string resMsg;
     Poco::StreamCopier::copyToString(rs, resMsg);
 
@@ -346,6 +349,12 @@ WopiStorage::WOPIFileInfo WopiStorage::getWOPIFileInfo(const Poco::URI& uriPubli
         canWrite = canWriteVar.isString() ? (canWriteVar.toString() == "true") : false;
         const auto postMessageOriginVar = getOrWarn(object, "PostMessageOrigin");
         postMessageOrigin = postMessageOriginVar.isString() ? postMessageOriginVar.toString() : "";
+        const auto hidePrintOptionVar = getOrWarn(object, "HidePrintOption");
+        hidePrintOption = hidePrintOptionVar.isString() ? (hidePrintOptionVar.toString() == "true") : false;
+        const auto hideSaveOptionVar = getOrWarn(object, "HideSaveOption");
+        hideSaveOption = hideSaveOptionVar.isString() ? (hideSaveOptionVar.toString() == "true") : false;
+        const auto hideExportOptionVar = getOrWarn(object, "HideExportOption");
+        hideExportOption = hideExportOptionVar.isString() ? (hideExportOptionVar.toString() == "true") : false;
         const auto enableOwnerTerminationVar = getOrWarn(object, "EnableOwnerTermination");
         enableOwnerTermination = enableOwnerTerminationVar.isString() ? (enableOwnerTerminationVar.toString() == "true") : false;
     }
@@ -358,7 +367,7 @@ WopiStorage::WOPIFileInfo WopiStorage::getWOPIFileInfo(const Poco::URI& uriPubli
         _fileInfo = FileInfo({filename, ownerId, Poco::Timestamp(), size});
     }
 
-    return WOPIFileInfo({userId, userName, canWrite, postMessageOrigin, enableOwnerTermination, callDuration});
+    return WOPIFileInfo({userId, userName, canWrite, postMessageOrigin, hidePrintOption, hideSaveOption, hideExportOption, enableOwnerTermination, callDuration});
 }
 
 /// uri format: http://server/<...>/wopi*/files/<id>/content
diff --git a/loolwsd/Storage.hpp b/loolwsd/Storage.hpp
index a1eb2cf..d116eec 100644
--- a/loolwsd/Storage.hpp
+++ b/loolwsd/Storage.hpp
@@ -169,12 +169,18 @@ public:
                      const std::string& username,
                      const bool userCanWrite,
                      const std::string& postMessageOrigin,
+                     const bool hidePrintOption,
+                     const bool hideSaveOption,
+                     const bool hideExportOption,
                      const bool enableOwnerTermination,
                      const std::chrono::duration<double> callDuration)
             : _userid(userid),
               _username(username),
               _userCanWrite(userCanWrite),
               _postMessageOrigin(postMessageOrigin),
+              _hidePrintOption(hidePrintOption),
+              _hideSaveOption(hideSaveOption),
+              _hideExportOption(hideExportOption),
               _enableOwnerTermination(enableOwnerTermination),
               _callDuration(callDuration)
             {
@@ -188,6 +194,12 @@ public:
         bool _userCanWrite;
         /// WOPI Post message property
         std::string _postMessageOrigin;
+        /// Hide print button from UI
+        bool _hidePrintOption;
+        /// Hide save button from UI
+        bool _hideSaveOption;
+        /// Hide 'Download as' button/menubar item from UI
+        bool _hideExportOption;
         /// If WOPI host has enabled owner termination feature on
         bool _enableOwnerTermination;
         /// Time it took to call WOPI's CheckFileInfo
commit 1ecd63cd385b5c4a34cac12fb143260c697b0be7
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 17:25:38 2016 +0530

    tdf#103641: Convert 'wopi:' message to JSON formatted message
    
    ... to accomdate other WOPI properties easily in future.
    
    Change-Id: Ic92364f06f4f16ebe8f9f128cd49087f6d72a4d1
    (cherry picked from commit 9c5928a87b91a58f37b8960453e9553c6020e1e8)

diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 87ffe91..77d643b 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -179,10 +179,10 @@ L.Socket = L.Class.extend({
 		}
 		else if (textMsg.startsWith('wopi: ')) {
 			// Handle WOPI related messages
-			textMsg = textMsg.substring('wopi: '.length);
+			var wopiInfo = JSON.parse(textMsg.substring(textMsg.indexOf('{')));
 			// Store postmessageorigin property in our WOPI handler, if it exists
-			if (this._map['wopi'] && textMsg.startsWith('postmessageorigin ')) {
-				this._map['wopi'].PostMessageOrigin = textMsg.substring('postmessageorigin '.length);
+			if (this._map['wopi'] && !!wopiInfo['PostMessageOrigin']) {
+				this._map['wopi'].PostMessageOrigin = wopiInfo['PostMessageOrigin'];
 				this._map['wopi'].DocumentLoadedTime = Date.now();
 				// Tell the host that we are ready now
 				this._map.fire('postMessage', {msgId: 'App_LoadingStatus', args: {'DocumentLoadedTime': this._map['wopi'].DocumentLoadedTime}});
diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp
index edc453e..179b2e5 100644
--- a/loolwsd/DocumentBroker.cpp
+++ b/loolwsd/DocumentBroker.cpp
@@ -12,7 +12,9 @@
 
 #include <cassert>
 #include <fstream>
+#include <sstream>
 
+#include <Poco/JSON/Object.h>
 #include <Poco/Path.h>
 #include <Poco/SHA1Engine.h>
 #include <Poco/StringTokenizer.h>
@@ -30,6 +32,7 @@
 
 using namespace LOOLProtocol;
 
+using Poco::JSON::Object;
 using Poco::StringTokenizer;
 
 void ChildProcess::socketProcessor()
@@ -238,7 +241,13 @@ bool DocumentBroker::load(std::shared_ptr<ClientSession>& session, const std::st
 
         if (!wopifileinfo._postMessageOrigin.empty())
         {
-            session->sendTextFrame("wopi: postmessageorigin " + wopifileinfo._postMessageOrigin);
+            // Construct a JSON containing relevant WOPI host properties
+            Object::Ptr wopiInfo = new Object();
+            wopiInfo->set("PostMessageOrigin", wopifileinfo._postMessageOrigin);
+            std::ostringstream ossWopiInfo;
+            wopiInfo->stringify(ossWopiInfo);
+
+            session->sendTextFrame("wopi: " + ossWopiInfo.str());
         }
 
         // Mark the session as 'Document owner' if WOPI hosts supports it
diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index 7fea786..9de1606 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -363,6 +363,13 @@ perm: <permission>
     <permission> can be one of 'edit', 'view', 'readonly'. Client must
     change the UI accordingly (disabling buttons etc.)
 
+wopi: <JSON>
+
+     Sent only in case storage is WOPI. Contains WOPI related
+     capabilities/information for loleaflet to act accordingly.
+
+     Properties mentioned:
+     PostMessageOrigin: See WOPI specs for more information
 
 child -> parent
 ===============
commit 97faec15130da9f2c3ba46c31a4a6a9ce0f988f9
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 17:11:14 2016 +0530

    loleaflet: Give id to these menu items
    
    So that it is easy to manipulate them in future by their
    identifier.
    
    Change-Id: I252aa448c26c23a00f0a3e717e1603b0d0277e67
    (cherry picked from commit 7cacabad40f2253b65f9485607691571577672cf)

diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index 639eef7..7eadfac 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -7,10 +7,10 @@ L.Control.Menubar = L.Control.extend({
 	// TODO: Some mechanism to stop the need to copy duplicate menus (eg. Help)
 	options: {
 		text:  [
-			{name: _('File'), type: 'menu', menu: [{name: _('Save'), type: 'unocommand', uno: '.uno:Save'},
+			{name: _('File'), type: 'menu', menu: [{name: _('Save'), id: 'save', type: 'unocommand', uno: '.uno:Save'},
 												   {name: _('Print'), id: 'print', type: 'action'},
 												   {name: _('See revision history'), id: 'rev-history', type: 'action'},
-												   {name: _('Download as'), type: 'menu', menu: [{name: _('PDF Document (.pdf)'), id: 'downloadas-pdf', type: 'action'},
+			                                       {name: _('Download as'), id: 'downloadas', type: 'menu', menu: [{name: _('PDF Document (.pdf)'), id: 'downloadas-pdf', type: 'action'},
 												   {name: _('ODF text document (.odt)'), id: 'downloadas-odt', type: 'action'},
 												   {name: _('Microsoft Word 2003 (.doc)'), id: 'downloadas-doc', type: 'action'},
 												   {name: _('Microsoft Word (.docx)'), id: 'downloadas-docx', type: 'action'}]}]
@@ -149,10 +149,10 @@ L.Control.Menubar = L.Control.extend({
 		],
 
 		presentation: [
-			{name: _('File'), type: 'menu', menu: [{name: _('Save'), type: 'unocommand', uno: '.uno:Save'},
+			{name: _('File'), type: 'menu', menu: [{name: _('Save'), id: 'save', type: 'unocommand', uno: '.uno:Save'},
 												   {name: _('Print'), id: 'print', type: 'action'},
 												   {name: _('See revision history'), id: 'rev-history', type: 'action'},
-												   {name: _('Download as'), type: 'menu', menu:	 [{name: _('PDF Document (.pdf)'), id: 'downloadas-pdf', type: 'action'},
+			                                       {name: _('Download as'), id: 'downloadas', type: 'menu', menu:	 [{name: _('PDF Document (.pdf)'), id: 'downloadas-pdf', type: 'action'},
 													{name: _('ODF presentation (.odp)'), id: 'downloadas-odp', type: 'action'},
 													{name: _('Microsoft Powerpoint 2003 (.ppt)'), id: 'downloadas-ppt', type: 'action'},
 													{name: _('Microsoft Powerpoint (.pptx)'), id: 'downloadas-pptx', type: 'action'}]}]
@@ -195,10 +195,10 @@ L.Control.Menubar = L.Control.extend({
 		],
 
 		spreadsheet: [
-			{name: _('File'), type: 'menu', menu: [{name: _('Save'), type: 'unocommand', uno: '.uno:Save'},
+			{name: _('File'), type: 'menu', menu: [{name: _('Save'), id: 'save', type: 'unocommand', uno: '.uno:Save'},
 												   {name: _('Print'), id: 'print', type: 'action'},
 												   {name: _('See revision history'), id: 'rev-history', type: 'action'},
-												   {name: _('Download as'), type: 'menu', menu: [{name: _('PDF Document (.pdf)'), id: 'downloadas-pdf', type: 'action'},
+			                                       {name: _('Download as'), id:'downloadas', type: 'menu', menu: [{name: _('PDF Document (.pdf)'), id: 'downloadas-pdf', type: 'action'},
 																						   {name: _('ODF spreadsheet (.ods)'), id: 'downloadas-ods', type: 'action'},
 																						   {name: _('Microsoft Excel 2003 (.xls)'), id: 'downloadas-xls', type: 'action'},
 																						   {name: _('Microsoft Excel (.xlsx)'), id: 'downloadas-xlsx', type: 'action'}]}]
commit ce61340c01d89b4fc7953429716ee4f4e1c230c7
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 10 21:14:18 2016 +0530

    loleaflet: Fix some silliness
    
    Change-Id: I8977d2f3a569d2442c34248a9b86fec9761fb0e2
    (cherry picked from commit df50c8fd34be3e255944ab02cd2027c5d1b414fb)

diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index d966306..8bac050 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -29,7 +29,7 @@ L.Map.WOPI = L.Handler.extend({
 		var msg = JSON.parse(e.data);
 		if (msg.MessageId === 'Get_Views') {
 			var getMembersRespVal = [];
-			for (var viewInfoIdx in this._map.viewInfo) {
+			for (var viewInfoIdx in this._map._viewInfo) {
 				getMembersRespVal.push({
 					ViewId: viewInfoIdx,
 					UserName: this._map._viewInfo[viewInfoIdx].username,
@@ -38,7 +38,7 @@ L.Map.WOPI = L.Handler.extend({
 				});
 			}
 
-			this._postMessage('Get_Views_Resp', getMembersRespVal);
+			this._postMessage({msgId: 'Get_Views_Resp', args: getMembersRespVal});
 		}
 		else if (msg.MessageId === 'Close_Session') {
 			this._map._socket.sendMessage('closedocument');


More information about the Libreoffice-commits mailing list