Commit 3cb14c36 authored by Robert Knight's avatar Robert Knight

Add `injectClient` method to HypothesisInjector

Expose the existing logic for injecting the client into a target frame
in HypothesisInjector as a public `injectClient` method and modify it to
wait for the document to be loaded if necessary. This method will be
used by the guest class to inject the client into specific frames when
requested by the current integration.

In the case where the frame is discovered by `FrameObserver` this means
that `onDocumentReady(frame)` will be called twice. That's OK because
the second call will just complete immediately if the frame is already
ready.
parent 05b6a932
import { FrameObserver } from './frame-observer'; import { onDocumentReady, FrameObserver } from './frame-observer';
/** /**
* @typedef {import('../types/annotator').Destroyable} Destroyable * @typedef {import('../types/annotator').Destroyable} Destroyable
...@@ -22,7 +22,7 @@ export class HypothesisInjector { ...@@ -22,7 +22,7 @@ export class HypothesisInjector {
this._config = config; this._config = config;
this._frameObserver = new FrameObserver( this._frameObserver = new FrameObserver(
element, element,
frame => this._addHypothesis(frame), frame => this.injectClient(frame),
() => {} () => {}
); );
} }
...@@ -35,19 +35,23 @@ export class HypothesisInjector { ...@@ -35,19 +35,23 @@ export class HypothesisInjector {
} }
/** /**
* Inject Hypothesis client into a newly-discovered iframe. * Inject Hypothesis client into a frame.
* *
* IMPORTANT: This method requires that the iframe is "accessible" * IMPORTANT: This method requires that the iframe is "accessible"
* (frame.contentDocument|contentWindow is not null) and "ready" (DOM content * (frame.contentDocument|contentWindow is not null).
* has been loaded and parsed) before the method is called. *
* This waits for the frame to finish loading before injecting the client.
* See {@link onDocumentReady}.
* *
* @param {HTMLIFrameElement} frame * @param {HTMLIFrameElement} frame
*/ */
_addHypothesis(frame) { async injectClient(frame) {
if (hasHypothesis(frame)) { if (hasHypothesis(frame)) {
return; return;
} }
await onDocumentReady(frame);
// Generate a random string to use as a frame ID. The format is not important. // Generate a random string to use as a frame ID. The format is not important.
const subFrameIdentifier = Math.random().toString().replace(/\D/g, ''); const subFrameIdentifier = Math.random().toString().replace(/\D/g, '');
const injectedConfig = { const injectedConfig = {
......
import { delay } from '../../../test-util/wait';
import { DEBOUNCE_WAIT, onDocumentReady } from '../../frame-observer'; import { DEBOUNCE_WAIT, onDocumentReady } from '../../frame-observer';
import { HypothesisInjector } from '../../hypothesis-injector'; import { HypothesisInjector } from '../../hypothesis-injector';
...@@ -10,8 +11,15 @@ describe('HypothesisInjector integration test', () => { ...@@ -10,8 +11,15 @@ describe('HypothesisInjector integration test', () => {
clientUrl: 'data:,Hypothesis', // empty data uri clientUrl: 'data:,Hypothesis', // empty data uri
}; };
function waitForFrameObserver() { // Wait for `FrameObserver` to discover added or removed iframes.
return new Promise(resolve => setTimeout(resolve, DEBOUNCE_WAIT + 10)); async function waitForFrameObserver() {
await delay(DEBOUNCE_WAIT + 10);
}
// Wait for `HypothesisInjector.injectClient` to finish injecting the client
// into the page.
async function waitForInjectClient() {
await delay(0);
} }
function getHypothesisScript(iframe) { function getHypothesisScript(iframe) {
...@@ -55,13 +63,13 @@ describe('HypothesisInjector integration test', () => { ...@@ -55,13 +63,13 @@ describe('HypothesisInjector integration test', () => {
// Now initialize // Now initialize
createHypothesisInjector(); createHypothesisInjector();
await onDocumentReady(validFrame); await waitForInjectClient();
assert.isNotNull( assert.isNotNull(
getHypothesisScript(validFrame), getHypothesisScript(validFrame),
'expected valid iframe to include the Hypothesis script' 'expected valid iframe to include the Hypothesis script'
); );
await onDocumentReady(invalidFrame);
assert.isNull( assert.isNull(
getHypothesisScript(invalidFrame), getHypothesisScript(invalidFrame),
'expected invalid iframe to not include the Hypothesis script' 'expected invalid iframe to not include the Hypothesis script'
...@@ -72,7 +80,7 @@ describe('HypothesisInjector integration test', () => { ...@@ -72,7 +80,7 @@ describe('HypothesisInjector integration test', () => {
const iframe = createAnnotatableIFrame(); const iframe = createAnnotatableIFrame();
createHypothesisInjector(); createHypothesisInjector();
await onDocumentReady(iframe); await waitForInjectClient();
const scriptElement = getHypothesisScript(iframe); const scriptElement = getHypothesisScript(iframe);
assert.isNotNull( assert.isNotNull(
...@@ -107,7 +115,7 @@ describe('HypothesisInjector integration test', () => { ...@@ -107,7 +115,7 @@ describe('HypothesisInjector integration test', () => {
const iframe = createAnnotatableIFrame(); const iframe = createAnnotatableIFrame();
await waitForFrameObserver(); await waitForFrameObserver();
await onDocumentReady(iframe); await waitForInjectClient();
assert.isNotNull( assert.isNotNull(
getHypothesisScript(iframe), getHypothesisScript(iframe),
'expected dynamically added iframe to include the Hypothesis script' 'expected dynamically added iframe to include the Hypothesis script'
...@@ -119,7 +127,7 @@ describe('HypothesisInjector integration test', () => { ...@@ -119,7 +127,7 @@ describe('HypothesisInjector integration test', () => {
// Now initialize // Now initialize
createHypothesisInjector(); createHypothesisInjector();
await onDocumentReady(iframe); await waitForInjectClient();
assert.isNotNull( assert.isNotNull(
getHypothesisScript(iframe), getHypothesisScript(iframe),
...@@ -133,7 +141,7 @@ describe('HypothesisInjector integration test', () => { ...@@ -133,7 +141,7 @@ describe('HypothesisInjector integration test', () => {
assert.isNull(getHypothesisScript(iframe)); assert.isNull(getHypothesisScript(iframe));
await waitForFrameObserver(); await waitForFrameObserver();
await onDocumentReady(iframe); await waitForInjectClient();
assert.isNotNull( assert.isNotNull(
getHypothesisScript(iframe), getHypothesisScript(iframe),
...@@ -149,7 +157,7 @@ describe('HypothesisInjector integration test', () => { ...@@ -149,7 +157,7 @@ describe('HypothesisInjector integration test', () => {
const iframe = createAnnotatableIFrame(); const iframe = createAnnotatableIFrame();
await waitForFrameObserver(); await waitForFrameObserver();
await onDocumentReady(iframe); await waitForInjectClient();
assert.isNotNull( assert.isNotNull(
getHypothesisScript(iframe), getHypothesisScript(iframe),
...@@ -163,7 +171,7 @@ describe('HypothesisInjector integration test', () => { ...@@ -163,7 +171,7 @@ describe('HypothesisInjector integration test', () => {
assert.isNull(getHypothesisScript(iframe)); assert.isNull(getHypothesisScript(iframe));
await waitForFrameObserver(); await waitForFrameObserver();
await onDocumentReady(iframe); await waitForInjectClient();
assert.isNotNull( assert.isNotNull(
getHypothesisScript(iframe), getHypothesisScript(iframe),
......
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