Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose a Javascript API for non-iframe embedded usage #155

Open
rtibbles opened this issue Sep 30, 2020 · 4 comments
Open

Expose a Javascript API for non-iframe embedded usage #155

rtibbles opened this issue Sep 30, 2020 · 4 comments

Comments

@rtibbles
Copy link

Would be good to be able to do a conventional import on the NPM package for use in Javascript - with the options passed as an options object to the constructor.

Would be happy to take a stab at this if there's any interest! Looks like a great project, and the bloomPub format has some really exciting features!

@JohnThomson
Copy link
Contributor

We think there may be some security issues with embedding bloom-player in a site without using an iframe, unless it is limited to reading books the site owner controls completely. Javascript embedded in the book would have complete access to everything in the host website.
But if you have a use case where that would not be a concern, we'd be glad to hear more about it.
I believe the changes needed would be fairly minor. BloomPlayer is internally already React components with well-defined APIs. There is some code that assumes BloomPlayerControls fills the body of the document, but this was a later development so it should not be widespread.

@rtibbles
Copy link
Author

I think things can definitely be achieved using the iframe approach, but it can make things simpler just to have a Javascript API. The way that I would leverage this in a secure way embedded in another site would be first to have a sandboxed iframe served from a different origin - this would be embedded in the parent page, and communicate via the postMessage API to allow data flow in and out.

Inside the sandboxed iframe, the bloom player would be initiated via the JS API, using parameters passed in via the postMessage API.

Admittedly, a further iframe inside the sandboxed iframe could be used and the details passed in via the GET params, but the JS API would give a bit more flexibility to reactively update without a full page refresh.

I did a first pass implementation of allowing the parameters to be passed into the InitBloomPlayerControls function:

export function InitBloomPlayerControls({
    url,
    allowToggleAppBar = false,
    showBackButton = false,
    initiallyShowAppBar = true,
    centerVertically = true,
    lang,
    useOriginalPageSize = false,
    hideFullScreenButton = false,
    element,
}: {
    url?: string,
    allowToggleAppBar?: boolean,
    showBackButton?: boolean,
    initiallyShowAppBar?: boolean,
    centerVertically?: boolean,
    lang?: string,
    useOriginalPageSize?: boolean,
    hideFullScreenButton?: boolean,
    element?: HTMLElement,
} = {}) {
    ReactDOM.render(
        <ThemeProvider theme={theme}>
            <BloomPlayerControls
                unencodedUrl={getQueryStringParamAndUnencode("url", url)}
                allowToggleAppBar={getBooleanUrlParam(
                    "allowToggleAppBar",
                    allowToggleAppBar
                )}
                showBackButton={getBooleanUrlParam("showBackButton", showBackButton)}
                initiallyShowAppBar={getBooleanUrlParam(
                    "initiallyShowAppBar",
                    initiallyShowAppBar
                )}
                centerVertically={getBooleanUrlParam("centerVertically", centerVertically)}
                initialLanguageCode={getQueryStringParamAndUnencode("lang", lang)}
                paused={false}
                locationOfDistFolder={""}
                useOriginalPageSize={getBooleanUrlParam(
                    "useOriginalPageSize",
                    useOriginalPageSize
                )}
                hideFullScreenButton={getBooleanUrlParam(
                    "hideFullScreenButton",
                    hideFullScreenButton
                )}
                extraButtons={[]}
            />
        </ThemeProvider>,
        element || document.getElementById("root")
    );
}

But had to make a separate build to export a library that did not auto-initialize the controls. I wonder if that initial call in bloom-player-root.ts could be move into the html file instead in a script tag?

@JohnThomson
Copy link
Contributor

That sounds a lot like what we're already doing. Bloom Player is already designed to live in a sandbox iframe and communicate with a host outside the iframe using various postMessage calls (look at externalContext.js if you haven't already) and to let other things be controlled by the iframe URL.
But you're right, it would add some flexibility to make bloomplayer.htm call InitBloomPlayerControls() in a separate script tag, so a different HTML file could use these components in another way. I'd be open to a PR along those lines.
I don't think your modified version of InitBloomPlayerControls is right, though. An init method that takes all the props as arguments should just pass them to the BloomPlayerControls element; I don't think it should also try to get them from the iframe URL. You could quite well leave InitBloomPlayerControls alone (or rename it InitBloomPlayerControlsFromUrl) and have another function that initializes the root DOM element using parameters passed to the function.
Of course, you might also just want to embed a BloomPlayerControls, or just a BloomPlayerCore, in other React components, and do ReactDOM.render() on the outermost.

@rtibbles
Copy link
Author

rtibbles commented Oct 1, 2020

Sounds good - yeah, this was just me playing around with the code to ensure I understood what each thing was doing, but your suggested implementation sounds good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants