Skip to content

Commit

Permalink
feat: add types for success and cancel messages for intents, increase…
Browse files Browse the repository at this point in the history
… security 👮
  • Loading branch information
gregorylegarec committed May 17, 2017
1 parent bfcae6e commit f07fad0
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 12 deletions.
32 changes: 25 additions & 7 deletions src/intents.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,24 @@ function injectService (url, element, intent, data) {
return reject(new Error('Intent error'))
}

return handshaken
? resolve(event.data)
: reject(new Error('Unexpected handshake message from intent service'))
if (handshaken && event.data.type === `intent-${intent._id}:cancel`) {
return resolve(null)
}

if (handshaken && event.data.type === `intent-${intent._id}:done`) {
return resolve(event.data.document)
}

if (!handshaken) {
return reject(new Error('Unexpected handshake message from intent service'))
}

// We may be in a state where the messageHandler is still attached to then
// window, but will not be needed anymore. For example, the service failed
// before adding the `unload` listener, so no `intent:cancel` message has
// never been sent.
// So we simply ignore other messages, and this listener will stay here,
// waiting for a message which will never come, forever (almost).
}

window.addEventListener('message', messageHandler)
Expand Down Expand Up @@ -101,14 +116,14 @@ export function createService (cozy, intentId, serviceWindow) {
.then(intent => {
let terminated = false

const terminate = (doc) => {
const terminate = (message) => {
if (terminated) throw new Error('Intent service has already been terminated')
terminated = true
serviceWindow.parent.postMessage(doc, intent.attributes.client)
serviceWindow.parent.postMessage(message, intent.attributes.client)
}

const cancel = () => {
terminate(null)
terminate({type: `intent-${intent._id}:cancel`})
}

// Prevent unfulfilled client promises when this window unloads for a
Expand All @@ -120,7 +135,10 @@ export function createService (cozy, intentId, serviceWindow) {
return {
getData: () => data,
getIntent: () => intent,
terminate: terminate,
terminate: (doc) => terminate({
type: `intent-${intent._id}:done`,
document: doc
}),
cancel: cancel
}
})
Expand Down
27 changes: 22 additions & 5 deletions test/unit/intents.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,10 @@ describe('Intents', function () {

const resolveEventMessageMock = {
origin: serviceUrl,
data: result,
data: {
type: 'intent-77bcc42c-0fd8-11e7-ac95-8f605f6e8338:done',
document: result
},
source: iframeWindowMock
}

Expand Down Expand Up @@ -348,8 +351,13 @@ describe('Intents', function () {

service.terminate(result)

const messageMatch = sinon.match({
type: 'intent-77bcc42c-0fd8-11e7-ac95-8f605f6e8338:done',
document: result
})

windowMock.parent.postMessage
.withArgs(result, expectedIntent.attributes.client).calledOnce.should.be.true()
.withArgs(messageMatch, expectedIntent.attributes.client).calledOnce.should.be.true()
})

it('should send result document to Client also with no params', async function () {
Expand All @@ -373,8 +381,13 @@ describe('Intents', function () {

service.terminate(result)

const messageMatch = sinon.match({
type: 'intent-77bcc42c-0fd8-11e7-ac95-8f605f6e8338:done',
document: result
})

window.parent.postMessage
.withArgs(result, expectedIntent.attributes.client).calledOnce.should.be.true()
.withArgs(messageMatch, expectedIntent.attributes.client).calledOnce.should.be.true()

delete global.window
})
Expand Down Expand Up @@ -424,8 +437,10 @@ describe('Intents', function () {

service.cancel()

const messageMatch = sinon.match({type: 'intent-77bcc42c-0fd8-11e7-ac95-8f605f6e8338:cancel'})

windowMock.parent.postMessage
.withArgs(null, expectedIntent.attributes.client).calledOnce.should.be.true()
.withArgs(messageMatch, expectedIntent.attributes.client).calledOnce.should.be.true()
})

it('should send null to Client also with no parameters', async function () {
Expand All @@ -445,8 +460,10 @@ describe('Intents', function () {

service.cancel()

const messageMatch = sinon.match({type: 'intent-77bcc42c-0fd8-11e7-ac95-8f605f6e8338:cancel'})

window.parent.postMessage
.withArgs(null, expectedIntent.attributes.client).calledOnce.should.be.true()
.withArgs(messageMatch, expectedIntent.attributes.client).calledOnce.should.be.true()

delete global.window
})
Expand Down

0 comments on commit f07fad0

Please sign in to comment.