Fix Collabora iframe loading and sandbox security

- Reverted to direct iframe src approach instead of form submission
- This avoids 'Form submission canceled' error
- Removed allow-same-origin from sandbox to improve security
- Added allow-popups-to-escape-sandbox for Collabora functionality
- Use direct URL with WOPISrc parameter instead of POST form
This commit is contained in:
Leon Bösche
2026-01-12 01:47:52 +01:00
parent 7bd1ab16da
commit 181fb0af93

View File

@@ -454,67 +454,40 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
} }
Widget _buildCollaboraIframe(String collaboraUrl) { Widget _buildCollaboraIframe(String collaboraUrl) {
// For Collabora Online, we need to use a form-based approach instead of iframe // For Collabora Online, create an iframe that loads the editor directly
// because loleaflet.html expects a POST request with WOPISrc in the body const String viewType = 'collabora-iframe';
const String viewType = 'collabora-form-container';
ui.platformViewRegistry.registerViewFactory( ui.platformViewRegistry.registerViewFactory(
viewType, viewType,
(int viewId) { (int viewId) {
// Create a container div for the form and iframe // Extract the WOPISrc value
final container = html.DivElement() final wopisrcValue = collaboraUrl.contains('WOPISrc=')
..style.width = '100%' ? Uri.decodeComponent(collaboraUrl.split('WOPISrc=')[1])
..style.height = '100%'
..style.margin = '0'
..style.padding = '0';
// Create a hidden form to POST to Collabora
final form = html.FormElement()
..method = 'POST'
..action = 'https://of.b0esche.cloud/loleaflet/dist/loleaflet.html'
..target = 'collabora-frame'
..style.display = 'none';
// Extract the WOPISrc value from the URL
final wopisrcValue = collaboraUrl.split('WOPISrc=').length > 1
? collaboraUrl.split('WOPISrc=')[1]
: ''; : '';
final wopisrcInput = html.InputElement()
..type = 'hidden'
..name = 'WOPISrc'
..value = wopisrcValue;
form.append(wopisrcInput);
container.append(form);
// Create the iframe // Create the iframe
final iframe = html.IFrameElement() final iframe = html.IFrameElement()
..name = 'collabora-frame'
..style.border = 'none' ..style.border = 'none'
..style.width = '100%' ..style.width = '100%'
..style.height = '100%' ..style.height = '100%'
..style.margin = '0' ..style.margin = '0'
..style.padding = '0'; ..style.padding = '0'
..setAttribute(
// Set sandbox attributes
iframe.setAttribute(
'sandbox',
'allow-same-origin allow-scripts allow-popups allow-forms allow-top-navigation allow-pointer-lock allow-presentation allow-modals allow-downloads',
);
iframe.setAttribute(
'allow', 'allow',
'microphone; camera; usb; autoplay; clipboard-read; clipboard-write', 'microphone; camera; usb; autoplay; clipboard-read; clipboard-write',
)
// Remove allow-same-origin and add allow-popups-to-escape-sandbox for better security
..setAttribute(
'sandbox',
'allow-scripts allow-popups allow-forms allow-pointer-lock allow-presentation allow-modals allow-downloads allow-popups-to-escape-sandbox',
); );
container.append(iframe); // Build the full Collabora URL
final collaboraPath =
'https://of.b0esche.cloud/loleaflet/dist/loleaflet.html';
iframe.src = '$collaboraPath?WOPISrc=$wopisrcValue';
// Submit the form to load the document return iframe;
form.submit();
return container;
}, },
); );