browser.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /**
  2. @module preloader browser
  3. */
  4. const _ = require('underscore');
  5. require('./include/common')('browser');
  6. const { ipcRenderer, webFrame, remote } = require('electron');
  7. const mist = require('./include/mistAPI.js');
  8. require('./include/getFavicon.js');
  9. require('./include/getMetaTags.js');
  10. require('./include/setBasePath')('interface');
  11. const packageJson = require('./../../package.json');
  12. const fs = remote.require('fs');
  13. const path = remote.require('path');
  14. // set navigator.language
  15. Object.defineProperty(navigator, 'language', {
  16. get() {
  17. return ipcRenderer.sendSync('backendAction_getLanguage');
  18. }
  19. });
  20. // notifiy the tab to store the webview id
  21. ipcRenderer.sendToHost('setWebviewId');
  22. const isValidJsonRpc = function(message) {
  23. return !!(
  24. Object.prototype.hasOwnProperty.call(message, 'method') ||
  25. Object.prototype.hasOwnProperty.call(message, 'id') ||
  26. Object.prototype.hasOwnProperty.call(message, 'params') ||
  27. Object.prototype.hasOwnProperty.call(message, 'jsonrpc')
  28. );
  29. };
  30. const sanatizeJsonRpc = function(message) {
  31. // sanitize
  32. return {
  33. jsonrpc: message.jsonrpc,
  34. id: message.id,
  35. method: message.method,
  36. params: message.params
  37. };
  38. };
  39. // Wait for post messages
  40. window.addEventListener('message', function message(event) {
  41. let data;
  42. try {
  43. data = JSON.parse(event.data);
  44. } catch (e) {
  45. data = event.data;
  46. }
  47. if (typeof data !== 'object') {
  48. return;
  49. }
  50. // EthereumProvider: connect
  51. if (data.type === 'create') {
  52. ipcRenderer.send('ipcProvider-create');
  53. // EthereumProvider: write
  54. } else if (data.type === 'write') {
  55. let messageIsArray = _.isArray(data.message);
  56. // only accept valid JSON rpc requests
  57. if (messageIsArray) {
  58. for (let i = 0; i < data.message.length; i++) {
  59. if (isValidJsonRpc(data.message[i])) {
  60. data.message[i] = sanatizeJsonRpc(data.message[i]);
  61. } else {
  62. return;
  63. }
  64. }
  65. } else {
  66. if (isValidJsonRpc(data.message)) {
  67. data.message = sanatizeJsonRpc(data.message);
  68. } else {
  69. return;
  70. }
  71. }
  72. // make sure we only send allowed properties
  73. ipcRenderer.send('ipcProvider-write', JSON.stringify(data.message));
  74. // mistAPI
  75. } else if (/^mistAPI_[a-z]/i.test(data.type)) {
  76. if (data.type === 'mistAPI_requestAccount') {
  77. ipcRenderer.send(data.type, data.message);
  78. } else {
  79. ipcRenderer.sendToHost(data.type, data.message);
  80. }
  81. }
  82. });
  83. const postMessage = function(payload) {
  84. if (typeof payload === 'object') {
  85. payload = JSON.stringify(payload);
  86. }
  87. window.postMessage(
  88. payload,
  89. !location.origin || location.origin === 'null' ? '*' : location.origin
  90. );
  91. };
  92. // custom Events
  93. ['uiAction_windowMessage', 'mistAPI_callMenuFunction'].forEach(function(type) {
  94. ipcRenderer.on(type, function onIpcRenderer(e, result) {
  95. // this type needs special packaging
  96. if (type === 'uiAction_windowMessage') {
  97. result = {
  98. type: arguments[1],
  99. error: arguments[2],
  100. value: arguments[3]
  101. };
  102. }
  103. postMessage({
  104. type: type,
  105. message: result
  106. });
  107. });
  108. });
  109. // add IPCbackend events
  110. ['data', 'error', 'end', 'timeout', 'connect'].forEach(function(type) {
  111. ipcRenderer.on(`ipcProvider-` + type, function onIpcRenderer(e, result) {
  112. postMessage({
  113. type: type,
  114. message: JSON.parse(result)
  115. });
  116. });
  117. });
  118. // load ethereumProvider
  119. const bignumber = fs
  120. .readFileSync(path.join(__dirname, '/injected/BigNumber.js'))
  121. .toString();
  122. const eventEmitter3 = fs
  123. .readFileSync(path.join(__dirname, '/injected/EventEmitter3.js'))
  124. .toString();
  125. let mistAPI = fs
  126. .readFileSync(path.join(__dirname, '/injected/mistAPI.js'))
  127. .toString();
  128. const ethereumProvider = fs
  129. .readFileSync(path.join(__dirname, '/injected/EthereumProvider.js'))
  130. .toString();
  131. mistAPI = mistAPI
  132. .replace('__version__', packageJson.version)
  133. .replace('__license__', packageJson.license)
  134. .replace('__platform__', process.platform)
  135. .replace(
  136. '__solidityVersion__',
  137. String(packageJson.dependencies.solc).match(/\d+\.\d+\.\d+/)[0]
  138. );
  139. webFrame.executeJavaScript(
  140. mistAPI + bignumber + eventEmitter3 + ethereumProvider
  141. );
  142. // notifiy the tab to store the webview id
  143. ipcRenderer.sendToHost('setWebviewId');
  144. // destroy the old socket
  145. ipcRenderer.send('ipcProvider-destroy');