Commit 60bf7317 authored by Sean Roberts's avatar Sean Roberts Committed by Robert Knight

Capture the client url to be used in subframes

parent 77db7150
......@@ -99,9 +99,6 @@ function LiveReloadServer(port, config) {
// Open the sidebar when the page loads
openSidebar: true,
// Subframe client embed code reference
embedScriptUrl: '${config.clientUrl}'
};
};
......
......@@ -10,20 +10,21 @@ var settingsFrom = require('./settings');
function configFrom(window_) {
var settings = settingsFrom(window_);
return {
sidebarAppUrl: settings.sidebarAppUrl,
query: settings.query,
annotations: settings.annotations,
showHighlights: settings.showHighlights,
openLoginForm: settings.hostPageSetting('openLoginForm', {allowInBrowserExt: true}),
openSidebar: settings.hostPageSetting('openSidebar', {allowInBrowserExt: true}),
branding: settings.hostPageSetting('branding'),
clientUrl: settings.clientUrl,
services: settings.hostPageSetting('services'),
embedScriptUrl: settings.hostPageSetting('embedScriptUrl'),
showHighlights: settings.showHighlights,
sidebarAppUrl: settings.sidebarAppUrl,
// Subframe identifier given when a frame is being embedded into
// by a top level client
subFrameIdentifier: settings.hostPageSetting('subFrameIdentifier'),
openLoginForm: settings.hostPageSetting('openLoginForm', {allowInBrowserExt: true}),
openSidebar: settings.hostPageSetting('openSidebar', {allowInBrowserExt: true}),
query: settings.query,
// Temporary feature flag override for 1st-party OAuth
oauthEnabled: settings.hostPageSetting('oauthEnabled'),
};
......
......@@ -10,10 +10,10 @@ function settingsFrom(window_) {
var configFuncSettings = configFuncSettingsFrom(window_);
/**
* Return the href URL of the first annotator link in the given document.
* Return the href URL of the first annotator sidebar link in the given document.
*
* Return the value of the href attribute of the first
* `<link type="application/annotator+html">` element in the given document.
* `<link type="application/annotator+html" rel="sidebar">` element in the given document.
*
* This URL is used as the src of the sidebar's iframe.
*
......@@ -24,14 +24,44 @@ function settingsFrom(window_) {
*
*/
function sidebarAppUrl() {
var link = window_.document.querySelector('link[type="application/annotator+html"]');
var link = window_.document.querySelector('link[type="application/annotator+html"][rel="sidebar"]');
if (!link) {
throw new Error('No application/annotator+html link in the document');
throw new Error('No application/annotator+html (rel="sidebar") link in the document');
}
if (!link.href) {
throw new Error('application/annotator+html link has no href');
throw new Error('application/annotator+html (rel="sidebar") link has no href');
}
return link.href;
}
/**
* Return the href URL of the first annotator client link in the given document.
*
* Return the value of the href attribute of the first
* `<link type="application/annotator+html" rel="hypothesis-client">` element in the given document.
*
* This URL is used to identify where the client is from and what url should be
* used inside of subframes
*
* @return {string} - The URL that the client is hosted from
*
* @throws {Error} - If there's no annotator link or the first annotator has
* no href.
*
*/
function clientUrl() {
var link = window_.document.querySelector('link[type="application/annotator+javascript"][rel="hypothesis-client"]');
if (!link) {
throw new Error('No application/annotator+javascript (rel="hypothesis-client") link in the document');
}
if (!link.href) {
throw new Error('application/annotator+javascript (rel="hypothesis-client") link has no href');
}
return link.href;
......@@ -126,9 +156,10 @@ function settingsFrom(window_) {
}
return {
get sidebarAppUrl() { return sidebarAppUrl(); },
get annotations() { return annotations(); },
get clientUrl() { return clientUrl(); },
get showHighlights() { return showHighlights(); },
get sidebarAppUrl() { return sidebarAppUrl(); },
get query() { return query(); },
hostPageSetting: hostPageSetting,
};
......
......@@ -30,9 +30,10 @@ describe('annotator.config.settingsFrom', function() {
});
describe('#sidebarAppUrl', function() {
function appendLinkToDocument(href) {
function appendSidebarLinkToDocument(href) {
var link = document.createElement('link');
link.type = 'application/annotator+html';
link.rel = 'sidebar';
if (href) {
link.href = href;
}
......@@ -44,7 +45,7 @@ describe('annotator.config.settingsFrom', function() {
var link;
beforeEach('add an application/annotator+html <link>', function() {
link = appendLinkToDocument('http://example.com/app.html');
link = appendSidebarLinkToDocument('http://example.com/app.html');
});
afterEach('tidy up the link', function() {
......@@ -61,8 +62,8 @@ describe('annotator.config.settingsFrom', function() {
var link2;
beforeEach('add two links to the document', function() {
link1 = appendLinkToDocument('http://example.com/app1');
link2 = appendLinkToDocument('http://example.com/app2');
link1 = appendSidebarLinkToDocument('http://example.com/app1');
link2 = appendSidebarLinkToDocument('http://example.com/app2');
});
afterEach('tidy up the links', function() {
......@@ -79,7 +80,7 @@ describe('annotator.config.settingsFrom', function() {
var link;
beforeEach('add an application/annotator+html <link> with no href', function() {
link = appendLinkToDocument();
link = appendSidebarLinkToDocument();
});
afterEach('tidy up the link', function() {
......@@ -91,7 +92,7 @@ describe('annotator.config.settingsFrom', function() {
function() {
settingsFrom(window).sidebarAppUrl; // eslint-disable-line no-unused-expressions
},
'application/annotator+html link has no href'
'application/annotator+html (rel="sidebar") link has no href'
);
});
});
......@@ -102,7 +103,87 @@ describe('annotator.config.settingsFrom', function() {
function() {
settingsFrom(window).sidebarAppUrl; // eslint-disable-line no-unused-expressions
},
'No application/annotator+html link in the document'
'No application/annotator+html (rel="sidebar") link in the document'
);
});
});
});
describe('#clientUrl', function() {
function appendClientUrlLinkToDocument(href) {
var link = document.createElement('link');
link.type = 'application/annotator+javascript';
link.rel = 'hypothesis-client';
if (href) {
link.href = href;
}
document.head.appendChild(link);
return link;
}
context("when there's an application/annotator+javascript link", function() {
var link;
beforeEach('add an application/annotator+javascript <link>', function() {
link = appendClientUrlLinkToDocument('http://example.com/app.html');
});
afterEach('tidy up the link', function() {
document.head.removeChild(link);
});
it('returns the href from the link', function() {
assert.equal(settingsFrom(window).clientUrl, 'http://example.com/app.html');
});
});
context('when there are multiple annotator+javascript links', function() {
var link1;
var link2;
beforeEach('add two links to the document', function() {
link1 = appendClientUrlLinkToDocument('http://example.com/app1');
link2 = appendClientUrlLinkToDocument('http://example.com/app2');
});
afterEach('tidy up the links', function() {
document.head.removeChild(link1);
document.head.removeChild(link2);
});
it('returns the href from the first one', function() {
assert.equal(settingsFrom(window).clientUrl, 'http://example.com/app1');
});
});
context('when the annotator+javascript link has no href', function() {
var link;
beforeEach('add an application/annotator+javascript <link> with no href', function() {
link = appendClientUrlLinkToDocument();
});
afterEach('tidy up the link', function() {
document.head.removeChild(link);
});
it('throws an error', function() {
assert.throws(
function() {
settingsFrom(window).clientUrl; // eslint-disable-line no-unused-expressions
},
'application/annotator+javascript (rel="hypothesis-client") link has no href'
);
});
});
context("when there's no annotator+javascript link", function() {
it('throws an error', function() {
assert.throws(
function() {
settingsFrom(window).clientUrl; // eslint-disable-line no-unused-expressions
},
'No application/annotator+javascript (rel="hypothesis-client") link in the document'
);
});
});
......
......@@ -37,8 +37,7 @@ var pluginClasses = {
CrossFrame: require('./plugin/cross-frame'),
};
var appLinkEl =
document.querySelector('link[type="application/annotator+html"]');
var appLinkEl = document.querySelector('link[type="application/annotator+html"][rel="sidebar"]');
var config = configFrom(window);
$.noConflict(true)(function() {
......
......@@ -64,14 +64,14 @@ module.exports = class CrossFrame extends Plugin
if !FrameUtil.hasHypothesis(frame)
# Take the embed script location from the config
# until an alternative solution comes around.
embedScriptUrl = config.embedScriptUrl
clientUrl = config.clientUrl
FrameUtil.isLoaded frame, () ->
subFrameIdentifier = discovery._generateToken()
frameIdentifiers.set(frame, subFrameIdentifier)
injectedConfig = Object.assign({}, config, {subFrameIdentifier})
FrameUtil.injectHypothesis(frame, embedScriptUrl, injectedConfig)
FrameUtil.injectHypothesis(frame, clientUrl, injectedConfig)
_iframeUnloaded = (frame) ->
bridge.call('destroyFrame', frameIdentifiers.get(frame))
......
......@@ -40,7 +40,7 @@ describe('CrossFrame multi-frame scenario', function () {
options = {
config: {
embedScriptUrl: 'data:,', // empty data uri
clientUrl: 'data:,', // empty data uri
},
on: sandbox.stub(),
emit: sandbox.stub(),
......@@ -111,7 +111,7 @@ describe('CrossFrame multi-frame scenario', function () {
isLoaded(frame, function () {
var scriptElement = frame.contentDocument.querySelector('script[src]');
assert(scriptElement, 'expected embed script to be injected');
assert.equal(scriptElement.src, options.config.embedScriptUrl,
assert.equal(scriptElement.src, options.config.clientUrl,
'unexpected embed script source');
resolve();
});
......
......@@ -45,11 +45,19 @@ function bootHypothesisClient(doc, config) {
// Register the URL of the sidebar app which the Hypothesis client should load.
// The <link> tag is also used by browser extensions etc. to detect the
// presence of the Hypothesis client on the page.
var baseUrl = doc.createElement('link');
baseUrl.rel = 'sidebar';
baseUrl.href = config.sidebarAppUrl;
baseUrl.type = 'application/annotator+html';
doc.head.appendChild(baseUrl);
var sidebarUrl = doc.createElement('link');
sidebarUrl.rel = 'sidebar';
sidebarUrl.href = config.sidebarAppUrl;
sidebarUrl.type = 'application/annotator+html';
doc.head.appendChild(sidebarUrl);
// Register the URL of the annotation client which is currently being used to drive
// annotation interactions.
var clientUrl = doc.createElement('link');
clientUrl.rel = 'hypothesis-client';
clientUrl.href = config.assetRoot + 'build/boot.js';
clientUrl.type = 'application/annotator+javascript';
doc.head.appendChild(clientUrl);
injectAssets(doc, config, [
// Vendor code and polyfills
......
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