feat(window post message communicator): Add uuid to frames

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2022-09-27 16:46:22 +02:00
parent 883f868399
commit 16bb83f74a
4 changed files with 43 additions and 22 deletions

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -7,6 +7,7 @@
import type { PropsWithChildren } from 'react'
import React, { createContext, useContext, useEffect, useMemo } from 'react'
import { EditorToRendererCommunicator } from '../../render-page/window-post-message-communicator/editor-to-renderer-communicator'
import { v4 as uuid } from 'uuid'
const EditorToRendererCommunicatorContext = createContext<EditorToRendererCommunicator | undefined>(undefined)
@ -27,8 +28,8 @@ export const useEditorToRendererCommunicator: () => EditorToRendererCommunicator
/**
* Provides a {@link EditorToRendererCommunicator editor to renderer communicator} for the child components via Context.
*/
export const EditorToRendererCommunicatorContextProvider: React.FC<PropsWithChildren<unknown>> = ({ children }) => {
const communicator = useMemo<EditorToRendererCommunicator>(() => new EditorToRendererCommunicator(), [])
export const EditorToRendererCommunicatorContextProvider: React.FC<PropsWithChildren> = ({ children }) => {
const communicator = useMemo<EditorToRendererCommunicator>(() => new EditorToRendererCommunicator(uuid()), [])
useEffect(() => {
const currentCommunicator = communicator

View file

@ -9,6 +9,7 @@ import React, { createContext, useContext, useEffect, useMemo } from 'react'
import { RendererToEditorCommunicator } from '../../render-page/window-post-message-communicator/renderer-to-editor-communicator'
import { CommunicationMessageType } from '../../render-page/window-post-message-communicator/rendering-message'
import { ORIGIN, useBaseUrl } from '../../../hooks/common/use-base-url'
import { useSingleStringUrlParameter } from '../../../hooks/common/use-single-string-url-parameter'
const RendererToEditorCommunicatorContext = createContext<RendererToEditorCommunicator | undefined>(undefined)
@ -28,7 +29,14 @@ export const useRendererToEditorCommunicator: () => RendererToEditorCommunicator
export const RendererToEditorCommunicatorContextProvider: React.FC<PropsWithChildren<unknown>> = ({ children }) => {
const editorOrigin = useBaseUrl(ORIGIN.EDITOR)
const communicator = useMemo<RendererToEditorCommunicator>(() => new RendererToEditorCommunicator(), [])
const uuid = useSingleStringUrlParameter('uuid', undefined)
const communicator = useMemo<RendererToEditorCommunicator>(() => {
if (uuid === undefined) {
throw new Error('no uuid found in url!')
} else {
return new RendererToEditorCommunicator(uuid)
}
}, [uuid])
useEffect(() => {
const currentCommunicator = communicator

View file

@ -8,6 +8,7 @@ import type { RefObject } from 'react'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { Logger } from '../../../../utils/logger'
import { ORIGIN, useBaseUrl } from '../../../../hooks/common/use-base-url'
import { useEditorToRendererCommunicator } from '../../render-context/editor-to-renderer-communicator-context-provider'
const log = new Logger('IframeLoader')
@ -19,14 +20,16 @@ const log = new Logger('IframeLoader')
*/
export const useForceRenderPageUrlOnIframeLoadCallback = (
iFrameReference: RefObject<HTMLIFrameElement>,
onNavigateAway?: () => void
onNavigateAway: () => void
): (() => void) => {
const iframeCommunicator = useEditorToRendererCommunicator()
const rendererBaseUrl = useBaseUrl(ORIGIN.RENDERER)
const forcedUrl = useMemo(() => {
const renderUrl = new URL(rendererBaseUrl)
renderUrl.pathname += 'render'
renderUrl.searchParams.set('uuid', iframeCommunicator.getUuid())
return renderUrl.toString()
}, [rendererBaseUrl])
}, [iframeCommunicator, rendererBaseUrl])
const redirectionInProgress = useRef<boolean>(false)
const loadCallback = useCallback(() => {

View file

@ -17,6 +17,11 @@ export type Handler<MESSAGES, MESSAGE_TYPE extends string> = (
values: Extract<MESSAGES, MessagePayload<MESSAGE_TYPE>>
) => void
export interface MessagePayloadWithUuid<MESSAGE_TYPE extends string> {
uuid: string
payload: MessagePayload<MESSAGE_TYPE>
}
export interface MessagePayload<MESSAGE_TYPE extends string> {
type: MESSAGE_TYPE
}
@ -36,12 +41,16 @@ export abstract class WindowPostMessageCommunicator<
private readonly log: Logger
private readonly boundListener: (event: MessageEvent) => void
public constructor() {
public constructor(private uuid: string) {
this.boundListener = this.handleEvent.bind(this)
this.communicationEnabled = false
this.log = this.createLogger()
}
public getUuid(): string {
return this.uuid
}
protected abstract createLogger(): Logger
/**
@ -104,7 +113,13 @@ export abstract class WindowPostMessageCommunicator<
)
}
this.log.debug('Sent event', message)
this.messageTarget.postMessage(message, this.targetOrigin)
this.messageTarget.postMessage(
{
uuid: this.uuid,
payload: message
} as MessagePayloadWithUuid<SEND_TYPE>,
this.targetOrigin
)
}
/**
@ -135,19 +150,13 @@ export abstract class WindowPostMessageCommunicator<
* @param event The received event
* @return {@link true} if the event was processed.
*/
protected handleEvent(event: MessageEvent<MessagePayload<RECEIVE_TYPE>>): void {
Optional.ofNullable(event.data).ifPresent((payload) => {
event.stopPropagation()
event.preventDefault()
this.processPayload(payload)
})
}
/**
* Processes a {@link MessagePayload message payload} using the correct {@link Handler handler}.
* @param payload The payload that should be processed
*/
private processPayload(payload: MessagePayload<string>): void {
this.emitter.emit(payload.type, payload)
protected handleEvent(event: MessageEvent<MessagePayloadWithUuid<RECEIVE_TYPE>>): void {
Optional.ofNullable(event.data)
.filter((value) => value.uuid === this.uuid)
.ifPresent((payload) => {
event.stopPropagation()
event.preventDefault()
this.emitter.emit(payload.payload.type, payload.payload)
})
}
}