No Description

WebViewJavascriptBridge_JS.m 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // This file contains the source for the Javascript side of the
  2. // WebViewJavascriptBridge. It is plaintext, but converted to an NSString
  3. // via some preprocessor tricks.
  4. //
  5. // Previous implementations of WebViewJavascriptBridge loaded the javascript source
  6. // from a resource. This worked fine for app developers, but library developers who
  7. // included the bridge into their library, awkwardly had to ask consumers of their
  8. // library to include the resource, violating their encapsulation. By including the
  9. // Javascript as a string resource, the encapsulation of the library is maintained.
  10. #import "WebViewJavascriptBridge_JS.h"
  11. NSString * WebViewJavascriptBridge_js() {
  12. #define __wvjb_js_func__(x) #x
  13. // BEGIN preprocessorJSCode
  14. static NSString * preprocessorJSCode = @__wvjb_js_func__(
  15. ;(function() {
  16. if (window.WebViewJavascriptBridge) {
  17. return;
  18. }
  19. if (!window.onerror) {
  20. window.onerror = function(msg, url, line) {
  21. console.log("WebViewJavascriptBridge: ERROR:" + msg + "@" + url + ":" + line);
  22. }
  23. }
  24. window.WebViewJavascriptBridge = {
  25. registerHandler: registerHandler,
  26. callHandler: callHandler,
  27. disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout,
  28. _fetchQueue: _fetchQueue,
  29. _handleMessageFromObjC: _handleMessageFromObjC
  30. };
  31. var messagingIframe;
  32. var sendMessageQueue = [];
  33. var messageHandlers = {};
  34. var CUSTOM_PROTOCOL_SCHEME = 'https';
  35. var QUEUE_HAS_MESSAGE = '__wvjb_queue_message__';
  36. var responseCallbacks = {};
  37. var uniqueId = 1;
  38. var dispatchMessagesWithTimeoutSafety = true;
  39. function registerHandler(handlerName, handler) {
  40. messageHandlers[handlerName] = handler;
  41. }
  42. function callHandler(handlerName, data, responseCallback) {
  43. if (arguments.length == 2 && typeof data == 'function') {
  44. responseCallback = data;
  45. data = null;
  46. }
  47. _doSend({ handlerName:handlerName, data:data }, responseCallback);
  48. }
  49. function disableJavscriptAlertBoxSafetyTimeout() {
  50. dispatchMessagesWithTimeoutSafety = false;
  51. }
  52. function _doSend(message, responseCallback) {
  53. if (responseCallback) {
  54. var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime();
  55. responseCallbacks[callbackId] = responseCallback;
  56. message['callbackId'] = callbackId;
  57. }
  58. sendMessageQueue.push(message);
  59. messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
  60. }
  61. function _fetchQueue() {
  62. var messageQueueString = JSON.stringify(sendMessageQueue);
  63. sendMessageQueue = [];
  64. return messageQueueString;
  65. }
  66. function _dispatchMessageFromObjC(messageJSON) {
  67. if (dispatchMessagesWithTimeoutSafety) {
  68. setTimeout(_doDispatchMessageFromObjC);
  69. } else {
  70. _doDispatchMessageFromObjC();
  71. }
  72. function _doDispatchMessageFromObjC() {
  73. var message = JSON.parse(messageJSON);
  74. var messageHandler;
  75. var responseCallback;
  76. if (message.responseId) {
  77. responseCallback = responseCallbacks[message.responseId];
  78. if (!responseCallback) {
  79. return;
  80. }
  81. responseCallback(message.responseData);
  82. delete responseCallbacks[message.responseId];
  83. } else {
  84. if (message.callbackId) {
  85. var callbackResponseId = message.callbackId;
  86. responseCallback = function(responseData) {
  87. _doSend({ handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData });
  88. };
  89. }
  90. var handler = messageHandlers[message.handlerName];
  91. if (!handler) {
  92. console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message);
  93. } else {
  94. handler(message.data, responseCallback);
  95. }
  96. }
  97. }
  98. }
  99. function _handleMessageFromObjC(messageJSON) {
  100. _dispatchMessageFromObjC(messageJSON);
  101. }
  102. messagingIframe = document.createElement('iframe');
  103. messagingIframe.style.display = 'none';
  104. messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
  105. document.documentElement.appendChild(messagingIframe);
  106. registerHandler("_disableJavascriptAlertBoxSafetyTimeout", disableJavscriptAlertBoxSafetyTimeout);
  107. setTimeout(_callWVJBCallbacks, 0);
  108. function _callWVJBCallbacks() {
  109. var callbacks = window.WVJBCallbacks;
  110. delete window.WVJBCallbacks;
  111. for (var i=0; i<callbacks.length; i++) {
  112. callbacks[i](WebViewJavascriptBridge);
  113. }
  114. }
  115. })();
  116. ); // END preprocessorJSCode
  117. #undef __wvjb_js_func__
  118. return preprocessorJSCode;
  119. };