2016-09-27 09:33:52 -04:00
|
|
|
(function () {
|
|
|
|
|
'use strict'
|
|
|
|
|
|
|
|
|
|
var ids = 0
|
2016-09-27 14:01:32 -04:00
|
|
|
var invokers = {}
|
|
|
|
|
var responseCallbacks = {}
|
2016-09-27 09:33:52 -04:00
|
|
|
|
2016-09-27 14:01:32 -04:00
|
|
|
//invoker has accept 2 arguments
|
|
|
|
|
//fn(args, result). result is a function which accept an argument.
|
|
|
|
|
//that argument is being used to send to caller as a result value.
|
|
|
|
|
//by using this function, we can support both sync and async operation
|
2016-09-27 20:53:03 -04:00
|
|
|
function register(sender, name, fn) {
|
2016-09-27 14:01:32 -04:00
|
|
|
invokers[name] = function (id, args) {
|
|
|
|
|
fn(args, function (result) {
|
2016-09-27 20:53:03 -04:00
|
|
|
sender({
|
2016-09-27 14:01:32 -04:00
|
|
|
id: id,
|
2016-09-28 01:35:14 -04:00
|
|
|
type: 'resolve',
|
2016-09-27 14:01:32 -04:00
|
|
|
result: result
|
|
|
|
|
})
|
2016-09-28 01:35:14 -04:00
|
|
|
}, function (err) {
|
|
|
|
|
sender({
|
|
|
|
|
id: id,
|
|
|
|
|
type: 'reject',
|
|
|
|
|
result: err
|
|
|
|
|
})
|
2016-09-27 14:01:32 -04:00
|
|
|
})
|
|
|
|
|
}
|
2016-09-27 09:33:52 -04:00
|
|
|
}
|
|
|
|
|
|
2016-09-28 01:35:14 -04:00
|
|
|
function invoke(sender, name, args, opt, callback) {
|
2016-09-27 14:01:32 -04:00
|
|
|
var id = ++ids
|
2016-09-28 01:35:14 -04:00
|
|
|
var target = {
|
|
|
|
|
callback: callback
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (opt) {
|
|
|
|
|
opt = {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!opt.timeout) {
|
|
|
|
|
opt.timeout = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (opt.timeout) {
|
|
|
|
|
target.timeoutHandler = setTimeout(function () {
|
|
|
|
|
onReject(id, 'timeout')
|
|
|
|
|
}, opt.timeout)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
responseCallbacks[id] = target
|
2016-09-27 09:33:52 -04:00
|
|
|
|
2016-09-27 20:53:03 -04:00
|
|
|
sender({
|
2016-09-27 14:01:32 -04:00
|
|
|
id: id,
|
|
|
|
|
type: 'invoke',
|
2016-09-27 09:33:52 -04:00
|
|
|
name: name,
|
|
|
|
|
args: args
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-27 14:01:32 -04:00
|
|
|
function onInvoke(payload) {
|
|
|
|
|
var invoker = invokers[payload.name]
|
|
|
|
|
if (invoker) {
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
invoker(payload.id, payload.args)
|
|
|
|
|
}, 15)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-28 01:35:14 -04:00
|
|
|
function onResolve(id, result) {
|
|
|
|
|
var target = responseCallbacks[id]
|
|
|
|
|
if (target) {
|
|
|
|
|
clearTimeout(target.timeoutHandler)
|
|
|
|
|
delete responseCallbacks[id]
|
2016-09-27 14:01:32 -04:00
|
|
|
setTimeout(function () {
|
2016-09-28 01:35:14 -04:00
|
|
|
target.callback(null, result)
|
|
|
|
|
}, 15)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onReject(id, result) {
|
|
|
|
|
var target = responseCallbacks[id]
|
|
|
|
|
if (target) {
|
|
|
|
|
clearTimeout(target.timeoutHandler)
|
|
|
|
|
delete responseCallbacks[id]
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
target(result, null)
|
2016-09-27 14:01:32 -04:00
|
|
|
}, 15)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onMessage(payload) {
|
|
|
|
|
if (typeof payload === 'string') {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-28 01:35:14 -04:00
|
|
|
// there are two types of payload
|
2016-09-27 14:01:32 -04:00
|
|
|
// invoke: { type: 'payload', id, name, args }
|
2016-09-28 01:35:14 -04:00
|
|
|
// resolve: { type: 'resolve', id, result }
|
|
|
|
|
// reject: { type: 'reject', id, result }
|
2016-09-27 14:01:32 -04:00
|
|
|
switch(payload.type) {
|
|
|
|
|
case 'invoke':
|
|
|
|
|
onInvoke(payload)
|
|
|
|
|
break
|
2016-09-28 01:35:14 -04:00
|
|
|
case 'resolve':
|
|
|
|
|
onResolve(payload.id, payload.result)
|
2016-09-27 14:01:32 -04:00
|
|
|
break
|
2016-09-28 01:35:14 -04:00
|
|
|
case 'reject':
|
|
|
|
|
onReject(payload.id, payload.result)
|
2016-09-27 14:01:32 -04:00
|
|
|
default:
|
|
|
|
|
//ignore
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//init this method register and attaches rpc to WebViewBridge.
|
|
|
|
|
//you can either check whether WebViewBridge.rpc is availebe or
|
|
|
|
|
//simply register to `webviewbridge:rpc` event.
|
2016-09-27 09:33:52 -04:00
|
|
|
function init(WebViewBridge) {
|
2016-09-27 20:53:03 -04:00
|
|
|
var rpc = {}
|
2016-09-28 01:35:14 -04:00
|
|
|
var sender = WebViewBridge.send
|
2016-09-27 09:33:52 -04:00
|
|
|
|
2016-09-27 20:53:03 -04:00
|
|
|
window.removeEventListener('webviewbridge:init', init)
|
|
|
|
|
WebViewBridge.addMessageListener(onMessage)
|
|
|
|
|
|
|
|
|
|
rpc.register = function (name, fn) {
|
|
|
|
|
register(sender, name, fn)
|
2016-09-27 09:33:52 -04:00
|
|
|
}
|
|
|
|
|
|
2016-09-28 01:35:14 -04:00
|
|
|
rpc.invoke = function (name, args, opt, callback) {
|
|
|
|
|
invoke(sender, name, args, opt, callback)
|
2016-09-27 20:53:03 -04:00
|
|
|
}
|
2016-09-27 14:01:32 -04:00
|
|
|
|
|
|
|
|
WebViewBridge.rpc = rpc
|
|
|
|
|
WebViewBridge.__dispatch__('webviewbridge:rpc', rpc)
|
2016-09-27 09:33:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (window.WebViewBridge) {
|
|
|
|
|
init(window.WebViewBridge)
|
|
|
|
|
} else {
|
|
|
|
|
window.addEventListener('webviewbridge:init', init)
|
|
|
|
|
}
|
|
|
|
|
}())
|