Commit 6cf7a391 authored by Robert Knight's avatar Robert Knight

Remove temporary client configuration from frame when client is unloaded

When the client is unloaded in a guest-only iframe, remove the client
configuration that was added by the `injectClient` function. This is
necessary for subsequent reloading of the client to work, as
`injectClient` aborts if the configuration already exists in a frame.

This change allows the client to be properly de-activated and then later
re-activated in a VitalSource book.
parent f18218f7
......@@ -48,7 +48,7 @@ export class HypothesisInjector {
}
/**
* Check if the client was added to a frame by {@link injectHypothesis}.
* Check if the client was added to a frame by {@link injectClient}.
*
* @param {HTMLIFrameElement} iframe
*/
......@@ -57,6 +57,16 @@ function hasHypothesis(iframe) {
return iframeDocument.querySelector('script.js-hypothesis-config') !== null;
}
/**
* Remove the temporary configuration data added to a document by {@link injectClient}.
*/
export function removeTemporaryClientConfig(document_ = document) {
const tempConfigEls = Array.from(
document_.querySelectorAll('script.js-temp-config')
);
tempConfigEls.forEach(el => el.remove());
}
/**
* Inject Hypothesis client into a frame.
*
......@@ -66,6 +76,10 @@ function hasHypothesis(iframe) {
* This waits for the frame to finish loading before injecting the client.
* See {@link onDocumentReady}.
*
* This function does nothing if the client has already been added to the frame.
* This is determined by the presence of temporary configuration `<script>`s
* added by this function, which can be removed with {@link removeTemporaryClientConfig}.
*
* @param {HTMLIFrameElement} frame
* @param {InjectConfig} config -
* @param {string} [frameId] - The ID for the guest frame. If none is provided,
......@@ -100,7 +114,7 @@ export async function injectClient(frame, config, frameId) {
};
const configElement = document.createElement('script');
configElement.className = 'js-hypothesis-config';
configElement.className = 'js-hypothesis-config js-temp-config';
configElement.type = 'application/json';
configElement.innerText = JSON.stringify(injectedConfig);
......
......@@ -18,7 +18,10 @@ import { getConfig } from './config/index';
import type { NotebookConfig } from './components/NotebookModal';
import { Guest } from './guest';
import type { GuestConfig } from './guest';
import { HypothesisInjector } from './hypothesis-injector';
import {
HypothesisInjector,
removeTemporaryClientConfig,
} from './hypothesis-injector';
import type { InjectConfig } from './hypothesis-injector';
import {
VitalSourceInjector,
......@@ -112,6 +115,10 @@ function init() {
// page by the boot script.
const clientAssets = document.querySelectorAll('[data-hypothesis-asset]');
clientAssets.forEach(el => el.remove());
// If this is a guest-only frame, remove client config added by the host
// frame. This enables the client to later be re-loaded in this frame.
removeTemporaryClientConfig();
});
}
......
......@@ -3,6 +3,7 @@ import { DEBOUNCE_WAIT, onNextDocumentReady } from '../../frame-observer';
import {
HypothesisInjector,
injectClient,
removeTemporaryClientConfig,
$imports,
} from '../../hypothesis-injector';
......@@ -72,6 +73,9 @@ describe('HypothesisInjector integration test', () => {
const configElement = frame.contentDocument.querySelector(
'.js-hypothesis-config'
);
if (!configElement) {
return null;
}
return JSON.parse(configElement.textContent);
}
......@@ -262,4 +266,26 @@ describe('HypothesisInjector integration test', () => {
'expected dynamically added iframe to include the Hypothesis script'
);
});
describe('removeTemporaryClientConfig', () => {
it('removes config `<script>`s added to page by `injectClient`', async () => {
const frame = document.createElement('iframe');
container.append(frame);
// Inject client into frame. Subsequent `injectClient` calls would be
// a no-op as the client is already injected.
await injectClient(frame, { clientUrl: 'https://hyp.is' });
assert.ok(extractClientConfig(frame));
// Remove client config. This should happen if the client is unloaded from
// the frame.
removeTemporaryClientConfig(frame.contentDocument);
assert.isNull(extractClientConfig(frame));
// After removing the temporary config, `injectClient` should once again
// be able to re-inject the client into the frame.
await injectClient(frame, { clientUrl: 'https://hyp.is' });
assert.ok(extractClientConfig(frame));
});
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment