PageRenderTime 52ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/react-native/Libraries/Utilities/WebSocketInterceptor.js

https://gitlab.com/_bogdanova/up2u
JavaScript | 219 lines | 143 code | 27 blank | 49 comment | 15 complexity | d7111d5a7ed8299c76d01c08b12bdd5d MD5 | raw file
  1. /**
  2. * Copyright (c) 2015-present, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. * @providesModule WebSocketInterceptor
  10. */
  11. 'use strict';
  12. const RCTWebSocketModule = require('NativeModules').WebSocketModule;
  13. const NativeEventEmitter = require('NativeEventEmitter');
  14. const base64 = require('base64-js');
  15. const originalRCTWebSocketConnect = RCTWebSocketModule.connect;
  16. const originalRCTWebSocketSend = RCTWebSocketModule.send;
  17. const originalRCTWebSocketSendBinary = RCTWebSocketModule.sendBinary;
  18. const originalRCTWebSocketClose = RCTWebSocketModule.close;
  19. let eventEmitter: NativeEventEmitter;
  20. let subscriptions: Array<EventSubscription>;
  21. let closeCallback;
  22. let sendCallback;
  23. let connectCallback;
  24. let onOpenCallback;
  25. let onMessageCallback;
  26. let onErrorCallback;
  27. let onCloseCallback;
  28. let isInterceptorEnabled = false;
  29. /**
  30. * A network interceptor which monkey-patches RCTWebSocketModule methods
  31. * to gather all websocket network requests/responses, in order to show
  32. * their information in the React Native inspector development tool.
  33. */
  34. const WebSocketInterceptor = {
  35. /**
  36. * Invoked when RCTWebSocketModule.close(...) is called.
  37. */
  38. setCloseCallback(callback) {
  39. closeCallback = callback;
  40. },
  41. /**
  42. * Invoked when RCTWebSocketModule.send(...) or sendBinary(...) is called.
  43. */
  44. setSendCallback(callback) {
  45. sendCallback = callback;
  46. },
  47. /**
  48. * Invoked when RCTWebSocketModule.connect(...) is called.
  49. */
  50. setConnectCallback(callback) {
  51. connectCallback = callback;
  52. },
  53. /**
  54. * Invoked when event "websocketOpen" happens.
  55. */
  56. setOnOpenCallback(callback) {
  57. onOpenCallback = callback;
  58. },
  59. /**
  60. * Invoked when event "websocketMessage" happens.
  61. */
  62. setOnMessageCallback(callback) {
  63. onMessageCallback = callback;
  64. },
  65. /**
  66. * Invoked when event "websocketFailed" happens.
  67. */
  68. setOnErrorCallback(callback) {
  69. onErrorCallback = callback;
  70. },
  71. /**
  72. * Invoked when event "websocketClosed" happens.
  73. */
  74. setOnCloseCallback(callback) {
  75. onCloseCallback = callback;
  76. },
  77. isInterceptorEnabled() {
  78. return isInterceptorEnabled;
  79. },
  80. _unregisterEvents() {
  81. subscriptions.forEach(e => e.remove());
  82. subscriptions = [];
  83. },
  84. /**
  85. * Add listeners to the RCTWebSocketModule events to intercept them.
  86. */
  87. _registerEvents() {
  88. subscriptions = [
  89. eventEmitter.addListener('websocketMessage', ev => {
  90. if (onMessageCallback) {
  91. onMessageCallback(
  92. ev.id,
  93. (ev.type === 'binary') ?
  94. WebSocketInterceptor._arrayBufferToString(ev.data) : ev.data,
  95. );
  96. }
  97. }),
  98. eventEmitter.addListener('websocketOpen', ev => {
  99. if (onOpenCallback) {
  100. onOpenCallback(ev.id);
  101. }
  102. }),
  103. eventEmitter.addListener('websocketClosed', ev => {
  104. if (onCloseCallback) {
  105. onCloseCallback(ev.id, {code: ev.code, reason: ev.reason});
  106. }
  107. }),
  108. eventEmitter.addListener('websocketFailed', ev => {
  109. if (onErrorCallback) {
  110. onErrorCallback(ev.id, {message: ev.message});
  111. }
  112. })
  113. ];
  114. },
  115. enableInterception() {
  116. if (isInterceptorEnabled) {
  117. return;
  118. }
  119. eventEmitter = new NativeEventEmitter(RCTWebSocketModule);
  120. WebSocketInterceptor._registerEvents();
  121. // Override `connect` method for all RCTWebSocketModule requests
  122. // to intercept the request url, protocols, options and socketId,
  123. // then pass them through the `connectCallback`.
  124. RCTWebSocketModule.connect = function(url, protocols, options, socketId) {
  125. if (connectCallback) {
  126. connectCallback(url, protocols, options, socketId);
  127. }
  128. originalRCTWebSocketConnect.apply(this, arguments);
  129. };
  130. // Override `send` method for all RCTWebSocketModule requests to intercept
  131. // the data sent, then pass them through the `sendCallback`.
  132. RCTWebSocketModule.send = function(data, socketId) {
  133. if (sendCallback) {
  134. sendCallback(data, socketId);
  135. }
  136. originalRCTWebSocketSend.apply(this, arguments);
  137. };
  138. // Override `sendBinary` method for all RCTWebSocketModule requests to
  139. // intercept the data sent, then pass them through the `sendCallback`.
  140. RCTWebSocketModule.sendBinary = function(data, socketId) {
  141. if (sendCallback) {
  142. sendCallback(WebSocketInterceptor._arrayBufferToString(data), socketId);
  143. }
  144. originalRCTWebSocketSendBinary.apply(this, arguments);
  145. };
  146. // Override `close` method for all RCTWebSocketModule requests to intercept
  147. // the close information, then pass them through the `closeCallback`.
  148. RCTWebSocketModule.close = function() {
  149. if (closeCallback) {
  150. if (arguments.length === 3) {
  151. closeCallback(arguments[0], arguments[1], arguments[2]);
  152. } else {
  153. closeCallback(null, null, arguments[0]);
  154. }
  155. }
  156. originalRCTWebSocketClose.apply(this, arguments);
  157. };
  158. isInterceptorEnabled = true;
  159. },
  160. _arrayBufferToString(data) {
  161. const value = base64.toByteArray(data).buffer;
  162. if (value === undefined || value === null) {
  163. return '(no value)';
  164. }
  165. if (typeof ArrayBuffer !== 'undefined' &&
  166. typeof Uint8Array !== 'undefined' &&
  167. value instanceof ArrayBuffer) {
  168. return `ArrayBuffer {${String(Array.from(new Uint8Array(value)))}}`;
  169. }
  170. return value;
  171. },
  172. // Unpatch RCTWebSocketModule methods and remove the callbacks.
  173. disableInterception() {
  174. if (!isInterceptorEnabled) {
  175. return;
  176. }
  177. isInterceptorEnabled = false;
  178. RCTWebSocketModule.send = originalRCTWebSocketSend;
  179. RCTWebSocketModule.sendBinary = originalRCTWebSocketSendBinary;
  180. RCTWebSocketModule.close = originalRCTWebSocketClose;
  181. RCTWebSocketModule.connect = originalRCTWebSocketConnect;
  182. connectCallback = null;
  183. closeCallback = null;
  184. sendCallback = null;
  185. onOpenCallback = null;
  186. onMessageCallback = null;
  187. onCloseCallback = null;
  188. onErrorCallback = null;
  189. WebSocketInterceptor._unregisterEvents();
  190. },
  191. };
  192. module.exports = WebSocketInterceptor;