Commit c817fa70 authored by csillag's avatar csillag

Simplify the bridge service

 - Remove unused support for options
 - Simplify the handling of scope
 - Make it a simpleton, and register the class as the constructor function.

Also updated all tests.

Kudos to @tilgovi for the feedback and ideas.
parent 719f2284
...@@ -20,8 +20,7 @@ CrossFrame = class Annotator.Plugin.CrossFrame extends Annotator.Plugin ...@@ -20,8 +20,7 @@ CrossFrame = class Annotator.Plugin.CrossFrame extends Annotator.Plugin
opts = extract(options, 'server') opts = extract(options, 'server')
discovery = new CrossFrame.Discovery(window, opts) discovery = new CrossFrame.Discovery(window, opts)
opts = extract(options, 'scope') bridge = new CrossFrame.Bridge()
bridge = new CrossFrame.Bridge(opts)
opts = extract(options, 'on', 'emit', 'formatter', 'parser') opts = extract(options, 'on', 'emit', 'formatter', 'parser')
annotationSync = new CrossFrame.AnnotationSync(bridge, opts) annotationSync = new CrossFrame.AnnotationSync(bridge, opts)
......
...@@ -51,10 +51,6 @@ describe 'Annotator.Plugin.CrossFrame', -> ...@@ -51,10 +51,6 @@ describe 'Annotator.Plugin.CrossFrame', ->
createCrossFrame() createCrossFrame()
assert.calledWith(cf.CrossFrame.Discovery) assert.calledWith(cf.CrossFrame.Discovery)
it 'passes the options along to the bridge', ->
createCrossFrame(scope: 'myscope')
assert.calledWith(cf.CrossFrame.Bridge, scope: 'myscope')
it 'instantiates the AnnotationSync component', -> it 'instantiates the AnnotationSync component', ->
createCrossFrame() createCrossFrame()
assert.called(cf.CrossFrame.AnnotationSync) assert.called(cf.CrossFrame.AnnotationSync)
......
$ = require('jquery') $ = require('jquery')
Channel = require('jschannel') Channel = require('jschannel')
# The Bridge service sets up a channel between frames
# and provides an events API on top of it.
class Bridge class Bridge
options:
# Scope identifier to distinguish this channel from any others
scope: 'bridge'
# Callback to invoke when a connection is established. The function is
# passed:
# - the newly created channel object
# - the window just connected to
onConnect: null
# Any callbacks for messages on the channel. Max one callback per method.
channelListeners: null
# Connected links to other frames # Connected links to other frames
links: null links: null
channelListeners: null channelListeners: null
onConnectListeners: null onConnectListeners: null
constructor: (options) -> constructor: ->
@options = $.extend(true, {}, @options, options)
@links = [] @links = []
@channelListeners = @options.channelListeners || {} @channelListeners = {}
@onConnectListeners = [] @onConnectListeners = []
if typeof @options.onConnect == 'function'
@onConnectListeners.push(@options.onConnect)
createChannel: (source, origin, token) -> createChannel: (source, origin, scope) ->
# Set up a channel # Set up a channel
scope = @options.scope + ':' + token
channelOptions = channelOptions =
window: source window: source
origin: origin origin: origin
...@@ -119,6 +104,6 @@ class Bridge ...@@ -119,6 +104,6 @@ class Bridge
channel = Channel.build(options) channel = Channel.build(options)
if angular? if angular?
angular.module('h').value('Bridge', Bridge) angular.module('h').service 'bridge', Bridge
else else
Annotator.Plugin.CrossFrame.Bridge = Bridge Annotator.Plugin.CrossFrame.Bridge = Bridge
...@@ -4,12 +4,12 @@ class CrossFrameService ...@@ -4,12 +4,12 @@ class CrossFrameService
this.inject = [ this.inject = [
'$rootScope', '$document', '$window', 'store', 'annotationUI' '$rootScope', '$document', '$window', 'store', 'annotationUI'
'Discovery', 'Bridge', 'Discovery', 'bridge',
'AnnotationSync', 'AnnotationUISync' 'AnnotationSync', 'AnnotationUISync'
] ]
constructor: ( constructor: (
$rootScope, $document, $window, store, annotationUI $rootScope, $document, $window, store, annotationUI
Discovery, Bridge, Discovery, bridge,
AnnotationSync, AnnotationUISync AnnotationSync, AnnotationUISync
) -> ) ->
@providers = [] @providers = []
...@@ -19,13 +19,6 @@ class CrossFrameService ...@@ -19,13 +19,6 @@ class CrossFrameService
server: true server: true
new Discovery($window, options) new Discovery($window, options)
# Set up the bridge plugin, which bridges the main annotation methods
# between the host page and the panel widget.
createBridge = ->
options =
scope: 'annotator:bridge'
new Bridge(options)
createAnnotationSync = (bridge) -> createAnnotationSync = (bridge) ->
whitelist = ['target', 'document', 'uri'] whitelist = ['target', 'document', 'uri']
options = options =
...@@ -63,7 +56,6 @@ class CrossFrameService ...@@ -63,7 +56,6 @@ class CrossFrameService
this.connect = -> this.connect = ->
discovery = createDiscovery() discovery = createDiscovery()
bridge = createBridge()
bridge.onConnect(addProvider) bridge.onConnect(addProvider)
annotationSync = createAnnotationSync(bridge) annotationSync = createAnnotationSync(bridge)
......
...@@ -60,7 +60,6 @@ module.exports = class Annotator.Guest extends Annotator ...@@ -60,7 +60,6 @@ module.exports = class Annotator.Guest extends Annotator
delete @options.app delete @options.app
cfOptions = cfOptions =
scope: 'annotator:bridge'
on: (event, handler) => on: (event, handler) =>
this.subscribe(event, handler) this.subscribe(event, handler)
emit: (event, args...) => emit: (event, args...) =>
......
...@@ -7,7 +7,7 @@ sinon.assert.expose assert, prefix: null ...@@ -7,7 +7,7 @@ sinon.assert.expose assert, prefix: null
describe 'Bridge', -> describe 'Bridge', ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
createBridge = null bridge = null
createChannel = null createChannel = null
before -> before ->
...@@ -15,9 +15,8 @@ describe 'Bridge', -> ...@@ -15,9 +15,8 @@ describe 'Bridge', ->
require('../bridge') require('../bridge')
beforeEach module('h') beforeEach module('h')
beforeEach inject (Bridge) -> beforeEach inject (_bridge_) ->
createBridge = (options) -> bridge = _bridge_
new Bridge(options)
createChannel = -> createChannel = ->
call: sandbox.stub() call: sandbox.stub()
...@@ -34,21 +33,19 @@ describe 'Bridge', -> ...@@ -34,21 +33,19 @@ describe 'Bridge', ->
describe '.createChannel', -> describe '.createChannel', ->
it 'creates a new channel with the provided options', -> it 'creates a new channel with the provided options', ->
Channel.build.returns(createChannel()) Channel.build.returns(createChannel())
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.called(Channel.build) assert.called(Channel.build)
assert.calledWith(Channel.build, { assert.calledWith(Channel.build, {
window: 'WINDOW' window: 'WINDOW'
origin: 'ORIGIN' origin: 'ORIGIN'
scope: 'bridge:TOKEN' scope: 'TOKEN'
onReady: sinon.match.func onReady: sinon.match.func
}) })
it 'adds the channel to the .links property', -> it 'adds the channel to the .links property', ->
channel = createChannel() channel = createChannel()
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.include(bridge.links, {channel: channel, window: 'WINDOW'}) assert.include(bridge.links, {channel: channel, window: 'WINDOW'})
...@@ -57,7 +54,6 @@ describe 'Bridge', -> ...@@ -57,7 +54,6 @@ describe 'Bridge', ->
channel = createChannel() channel = createChannel()
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.on('message1', sinon.spy()) bridge.on('message1', sinon.spy())
bridge.on('message2', sinon.spy()) bridge.on('message2', sinon.spy())
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
...@@ -70,7 +66,6 @@ describe 'Bridge', -> ...@@ -70,7 +66,6 @@ describe 'Bridge', ->
channel = createChannel() channel = createChannel()
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
ret = bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') ret = bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.equal(ret, channel) assert.equal(ret, channel)
...@@ -80,7 +75,6 @@ describe 'Bridge', -> ...@@ -80,7 +75,6 @@ describe 'Bridge', ->
channel = createChannel() channel = createChannel()
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1'}) bridge.call({method: 'method1', params: 'params1'})
...@@ -93,7 +87,6 @@ describe 'Bridge', -> ...@@ -93,7 +87,6 @@ describe 'Bridge', ->
channel = createChannel() channel = createChannel()
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1'}) bridge.call({method: 'method1', params: 'params1'})
...@@ -108,7 +101,6 @@ describe 'Bridge', -> ...@@ -108,7 +101,6 @@ describe 'Bridge', ->
callback = sandbox.stub() callback = sandbox.stub()
bridge = createBridge()
Channel.build.returns(channel1) Channel.build.returns(channel1)
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
Channel.build.returns(channel2) Channel.build.returns(channel2)
...@@ -127,7 +119,6 @@ describe 'Bridge', -> ...@@ -127,7 +119,6 @@ describe 'Bridge', ->
channel2.call.yieldsTo('success', 'result2') channel2.call.yieldsTo('success', 'result2')
callback = sandbox.stub() callback = sandbox.stub()
bridge = createBridge()
Channel.build.returns(channel1) Channel.build.returns(channel1)
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
...@@ -144,7 +135,6 @@ describe 'Bridge', -> ...@@ -144,7 +135,6 @@ describe 'Bridge', ->
channel.call.yieldsTo('error', new Error(''), 'A reason for the error') channel.call.yieldsTo('error', new Error(''), 'A reason for the error')
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()}) bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()})
...@@ -155,7 +145,6 @@ describe 'Bridge', -> ...@@ -155,7 +145,6 @@ describe 'Bridge', ->
channel.call.yieldsTo('error', new Error(''), 'A reason for the error') channel.call.yieldsTo('error', new Error(''), 'A reason for the error')
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()}) bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()})
bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()}) bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()})
...@@ -168,7 +157,6 @@ describe 'Bridge', -> ...@@ -168,7 +157,6 @@ describe 'Bridge', ->
Channel.build.returns(channel) Channel.build.returns(channel)
callback = sandbox.stub() callback = sandbox.stub()
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1', callback: callback}) bridge.call({method: 'method1', params: 'params1', callback: callback})
...@@ -180,7 +168,6 @@ describe 'Bridge', -> ...@@ -180,7 +168,6 @@ describe 'Bridge', ->
channel.call.yieldsTo('error', 'timeout_error', 'timeout') channel.call.yieldsTo('error', 'timeout_error', 'timeout')
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
ret = bridge.call({method: 'method1', params: 'params1'}) ret = bridge.call({method: 'method1', params: 'params1'})
assert.isFunction(ret.then) assert.isFunction(ret.then)
...@@ -190,7 +177,6 @@ describe 'Bridge', -> ...@@ -190,7 +177,6 @@ describe 'Bridge', ->
message = {method: 'message1', params: 'params'} message = {method: 'message1', params: 'params'}
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.notify(message) bridge.notify(message)
...@@ -202,7 +188,6 @@ describe 'Bridge', -> ...@@ -202,7 +188,6 @@ describe 'Bridge', ->
channel = createChannel() channel = createChannel()
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.on('message1', sandbox.spy()) bridge.on('message1', sandbox.spy())
...@@ -210,7 +195,6 @@ describe 'Bridge', -> ...@@ -210,7 +195,6 @@ describe 'Bridge', ->
assert.calledWith(channel.bind, 'message1', sinon.match.func) assert.calledWith(channel.bind, 'message1', sinon.match.func)
it 'only allows one message to be registered per method', -> it 'only allows one message to be registered per method', ->
bridge = createBridge()
bridge.on('message1', sandbox.spy()) bridge.on('message1', sandbox.spy())
assert.throws -> assert.throws ->
bridge.on('message1', sandbox.spy()) bridge.on('message1', sandbox.spy())
...@@ -220,7 +204,6 @@ describe 'Bridge', -> ...@@ -220,7 +204,6 @@ describe 'Bridge', ->
channel = createChannel() channel = createChannel()
Channel.build.returns(channel) Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.off('message1', sandbox.spy()) bridge.off('message1', sandbox.spy())
...@@ -229,7 +212,6 @@ describe 'Bridge', -> ...@@ -229,7 +212,6 @@ describe 'Bridge', ->
channel2 = createChannel() channel2 = createChannel()
Channel.build.returns(channel1) Channel.build.returns(channel1)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.off('message1', sandbox.spy()) bridge.off('message1', sandbox.spy())
...@@ -243,7 +225,6 @@ describe 'Bridge', -> ...@@ -243,7 +225,6 @@ describe 'Bridge', ->
Channel.build.yieldsTo('onReady', channel) Channel.build.yieldsTo('onReady', channel)
callback = sandbox.stub() callback = sandbox.stub()
bridge = createBridge()
bridge.onConnect(callback) bridge.onConnect(callback)
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN') bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
...@@ -258,7 +239,6 @@ describe 'Bridge', -> ...@@ -258,7 +239,6 @@ describe 'Bridge', ->
callback1 = sandbox.stub() callback1 = sandbox.stub()
callback2 = sandbox.stub() callback2 = sandbox.stub()
bridge = createBridge()
bridge.onConnect(callback1) bridge.onConnect(callback1)
bridge.onConnect(callback2) bridge.onConnect(callback2)
......
...@@ -42,8 +42,7 @@ describe 'CrossFrameService', -> ...@@ -42,8 +42,7 @@ describe 'CrossFrameService', ->
$provide.value('annotationUI', fakeAnnotationUI) $provide.value('annotationUI', fakeAnnotationUI)
$provide.value('Discovery', $provide.value('Discovery',
sandbox.stub().returns(fakeDiscovery)) sandbox.stub().returns(fakeDiscovery))
$provide.value('Bridge', $provide.value('bridge', fakeBridge)
sandbox.stub().returns(fakeBridge))
$provide.value('AnnotationSync', $provide.value('AnnotationSync',
sandbox.stub().returns(fakeAnnotationSync)) sandbox.stub().returns(fakeAnnotationSync))
$provide.value('AnnotationUISync', $provide.value('AnnotationUISync',
......
...@@ -39,10 +39,6 @@ describe 'Annotator.Guest', -> ...@@ -39,10 +39,6 @@ describe 'Annotator.Guest', ->
sandbox.restore() sandbox.restore()
describe 'setting up the bridge', -> describe 'setting up the bridge', ->
it 'sets the scope for the cross frame bridge', ->
guest = createGuest()
options = Annotator.Plugin.CrossFrame.lastCall.args[1]
assert.equal(options.scope, 'annotator:bridge')
it 'provides an event bus for the annotation sync module', -> it 'provides an event bus for the annotation sync module', ->
guest = createGuest() guest = createGuest()
......
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