单军华
2018-07-11 7b02207537d35bfa1714bf8beafc921f717d100a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
;(function() {
    if (window.WebViewJavascriptBridge) { return }
    var messagingIframe
    var sendMessageQueue = []
    var receiveMessageQueue = []
    var messageHandlers = {}
    
    var MESSAGE_SEPARATOR = '__WVJB_MESSAGE_SEPERATOR__'
    var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme'
    var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__'
    
    var responseCallbacks = {}
    var uniqueId = 1
    
    function _createQueueReadyIframe(doc) {
        messagingIframe = doc.createElement('iframe')
        messagingIframe.style.display = 'none'
        doc.documentElement.appendChild(messagingIframe)
    }
 
    function init(messageHandler) {
        if (WebViewJavascriptBridge._messageHandler) { throw new Error('WebViewJavascriptBridge.init called twice') }
        WebViewJavascriptBridge._messageHandler = messageHandler
        var receivedMessages = receiveMessageQueue
        receiveMessageQueue = null
        for (var i=0; i<receivedMessages.length; i++) {
            _dispatchMessageFromObjC(receivedMessages[i])
        }
    }
 
    function send(data, responseCallback) {
        _doSend({ data:data }, responseCallback)
    }
    
    function registerHandler(handlerName, handler) {
        messageHandlers[handlerName] = handler
    }
    
    function callHandler(handlerName, data, responseCallback) {
        _doSend({ data:data, handlerName:handlerName }, responseCallback)
    }
    
    function _doSend(message, responseCallback) {
        if (responseCallback) {
            var callbackId = 'js_cb_'+(uniqueId++)
            responseCallbacks[callbackId] = responseCallback
            message['callbackId'] = callbackId
        }
        sendMessageQueue.push(JSON.stringify(message))
        messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE
    }
 
    function _fetchQueue() {
        var messageQueueString = sendMessageQueue.join(MESSAGE_SEPARATOR)
        sendMessageQueue = []
        return messageQueueString
    }
 
    function _dispatchMessageFromObjC(messageJSON) {
        setTimeout(function _timeoutDispatchMessageFromObjC() {
            var message = JSON.parse(messageJSON)
            var messageHandler
            if (message.responseId) {
                var responseCallback = responseCallbacks[message.responseId]
 
                responseCallback(message.error, message.responseData)
                delete responseCallbacks[message.responseId]
            } else {
                var response                            
                if (message.callbackId) {
                    var callbackResponseId = message.callbackId
                    response = {
                        respondWith: function(responseData) {
                            _doSend({ responseId:callbackResponseId, responseData:responseData })
                        },
                        respondWithError: function(error) {
                            _doSend({ responseId:callbackResponseId, error:error })
                        }
                    }
                }
                
                var handler = WebViewJavascriptBridge._messageHandler
 
                if (message.handlerName) {
                    handler = messageHandlers[message.handlerName]
                }
                
                try {
                    handler(message.data, response)
                } catch(exception) {
                    console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
                }
            }
        })
    }
    
    function _handleMessageFromObjC(messageJSON) {
 
        if (receiveMessageQueue) {
            receiveMessageQueue.push(messageJSON)
        } else {
            _dispatchMessageFromObjC(messageJSON)
        }
    }
 
    window.WebViewJavascriptBridge = {
        init: init,
        send: send,
        registerHandler: registerHandler,
        callHandler: callHandler,
        _fetchQueue: _fetchQueue,
        _handleMessageFromObjC: _handleMessageFromObjC
    }
 
    var doc = document
    _createQueueReadyIframe(doc)
    var readyEvent = doc.createEvent('Events')
    readyEvent.initEvent('WebViewJavascriptBridgeReady')
    readyEvent.bridge = WebViewJavascriptBridge
    doc.dispatchEvent(readyEvent)
})();