# HG changeset patch # User Sebastien Jodogne # Date 1606466042 -3600 # Node ID 5726528039295f32b52d2f164a4b1b2126c1977c # Parent a691ab50d4162a15e2359eae857bfd723ebff17e bootstrapping the Stone Web viewer configuration file diff -r a691ab50d416 -r 572652803929 Applications/StoneWebViewer/NOTES.txt --- a/Applications/StoneWebViewer/NOTES.txt Thu Nov 26 19:46:33 2020 +0100 +++ b/Applications/StoneWebViewer/NOTES.txt Fri Nov 27 09:34:02 2020 +0100 @@ -47,3 +47,38 @@ If the "selectedStudies" is not provided, then all the studies are displayed at the startup. + +Dynamic actions using messages +============================== + +Some actions can be dynamically triggered in the Stone Web viewer from +another Web page. This is done by using the "window.postMessage()" +primitive of JavaScript: +https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage + +Each message must be a JSON object containing at least the "type" +field. The latter field indicates the type of action to be triggered. + +For security, the "ExpectedMessageOrigin" configuration option of the +Stone Web viewer must have been set to the expected origin of the +messages. Otherwise, the Stone Web viewer will reject the message. + + +Action of type "show-osirix-annotations" +---------------------------------------- + +This action loads a set of ROIs exported from OsiriX. The ROIs must +use the XML file format of OsiriX. + +The parent DICOM study containing the annotation(s) must have been +loaded by the Stone Web viewer beforehand. The Stone Web viewer shall +automatically focus on one instance that is associated with the ROIs. + +The JSON message must contain the following fields: + +- "type" must be equal to "show-osirix-annotations" + +- "xml" must contain the XML file generated by OsiriX + +- "clear" is a Boolean to indicate whether to clear the annotations + that have previously been opened. diff -r a691ab50d416 -r 572652803929 Applications/StoneWebViewer/WebApplication/app.js --- a/Applications/StoneWebViewer/WebApplication/app.js Thu Nov 26 19:46:33 2020 +0100 +++ b/Applications/StoneWebViewer/WebApplication/app.js Fri Nov 27 09:34:02 2020 +0100 @@ -19,6 +19,9 @@ **/ +var CONFIGURATION_SOURCE = 'configuration.json'; +var WASM_SOURCE = 'StoneWebViewer.js'; + var COLORS = [ 'blue', 'red', 'green', 'yellow', 'violet' ]; var SERIES_INSTANCE_UID = '0020,000e'; var STUDY_INSTANCE_UID = '0020,000d'; @@ -28,6 +31,8 @@ // Registry of the PDF series for which the instance metadata is still waiting var pendingSeriesPdf_ = {}; +var globalConfiguration_ = {}; + function getParameterFromUrl(key) { var url = window.location.search.substring(1); @@ -809,6 +814,16 @@ +function ParseJsonWithComments(json) +{ + if (typeof(json) == 'string') { + // https://stackoverflow.com/a/62945875/881731 + return JSON.parse(json.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, + (m, g) => g ? "" : m)); + } else { + return json; + } +} $(document).ready(function() { @@ -821,31 +836,36 @@ //app.modalWarning = true; + axios.get(CONFIGURATION_SOURCE) + .then(function(response) { + globalConfiguration_ = ParseJsonWithComments(response.data); + + // Option 1: Loading script using plain HTML + + /* + var script = document.createElement('script'); + script.src = WASM_SOURCE; + script.type = 'text/javascript'; + document.body.appendChild(script); + */ - var wasmSource = 'StoneWebViewer.js'; - - // Option 1: Loading script using plain HTML - - /* - var script = document.createElement('script'); - script.src = wasmSource; - script.type = 'text/javascript'; - document.body.appendChild(script); - */ + // Option 2: Loading script using AJAX (gives the opportunity to + // explicitly report errors) - // Option 2: Loading script using AJAX (gives the opportunity to - // report explicit errors) - - axios.get(wasmSource) - .then(function (response) { - var script = document.createElement('script'); - script.innerHTML = response.data; - script.type = 'text/javascript'; - document.body.appendChild(script); + axios.get(WASM_SOURCE) + .then(function (response) { + var script = document.createElement('script'); + script.innerHTML = response.data; + script.type = 'text/javascript'; + document.body.appendChild(script); + }) + .catch(function (error) { + alert('Cannot load the WebAssembly framework'); + }); }) .catch(function (error) { - alert('Cannot load the WebAssembly framework'); - }); + alert('Cannot load the configuration file'); + }); }); @@ -860,51 +880,29 @@ document.onselectstart = new Function ('return false'); - - - - - -//var expectedOrigin = 'http://localhost:8042'; -var expectedOrigin = ''; // TODO - INSECURE - CONFIGURATION - window.addEventListener('message', function(e) { if ('type' in e.data) { - if (expectedOrigin != '' && - e.origin !== expectedOrigin) { - alert('Bad origin for the message'); - return; + var expectedOrigin = globalConfiguration_['ExpectedMessageOrigin']; + + if (expectedOrigin === undefined) { + alert('Dynamic actions are disabled in the Stone Web viewer, ' + + 'set the configuration option "ExpectedMessageOrigin".'); + } + else if (expectedOrigin != '*' && + e.origin !== expectedOrigin) { + alert('Bad origin for a dynamic action in the Stone Web viewer: "' + e.origin + + '", whereas the message must have origin: "' + expectedOrigin + '"'); } - - if (e.data.type == 'show-osirix-annotations') { + else if (e.data.type == 'show-osirix-annotations') { var clear = true; // Whether to clear previous annotations if ('clear' in e.data) { clear = e.data.clear; } app.LoadOsiriXAnnotations(e.data.xml, clear); - } else { - console.log('Unknown message type: ' + e.data.type); + } + else { + alert('Unknown type of dynamic action in the Stone Web viewer: ' + e.data.type); } } }); - - -function Test() -{ - var s = [ 'length.xml', 'arrow.xml', 'text.xml', 'angle.xml' ]; - - for (var i = 0; i < s.length; i++) { - axios.get(s[i]) - .then(function (response) { - //var targetOrigin = 'http://localhost:8000'; - var targetOrigin = '*'; // TODO - INSECURE - - window.postMessage({ - 'type': 'show-osirix-annotations', - 'xml': response.data, - 'clear': false - }, targetOrigin); - }); - } -} diff -r a691ab50d416 -r 572652803929 Applications/StoneWebViewer/WebApplication/configuration.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/StoneWebViewer/WebApplication/configuration.json Fri Nov 27 09:34:02 2020 +0100 @@ -0,0 +1,11 @@ +{ + /** + * The allowed origin for messages corresponding to dynamic actions + * triggered by another Web page using "window.postMessage()". The + * special value "*" will allow any origin, which is an insecure + * value to be used only during development. If this option is not + * set, all the requests for dynamic actions will be rejected. + * https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage + **/ + "ExpectedMessageOrigin" : "http://localhost:8042" +} diff -r a691ab50d416 -r 572652803929 Applications/StoneWebViewer/WebAssembly/CMakeLists.txt --- a/Applications/StoneWebViewer/WebAssembly/CMakeLists.txt Thu Nov 26 19:46:33 2020 +0100 +++ b/Applications/StoneWebViewer/WebAssembly/CMakeLists.txt Fri Nov 27 09:34:02 2020 +0100 @@ -157,6 +157,7 @@ ${CMAKE_SOURCE_DIR}/../WebApplication/app-fixes.css ${CMAKE_SOURCE_DIR}/../WebApplication/app.css ${CMAKE_SOURCE_DIR}/../WebApplication/app.js + ${CMAKE_SOURCE_DIR}/../WebApplication/configuration.json ${CMAKE_SOURCE_DIR}/../WebApplication/index.html ${CMAKE_SOURCE_DIR}/../WebApplication/open-sans.css ${CMAKE_SOURCE_DIR}/../WebApplication/pdf-viewer.js