chcp.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. var exec = require('cordova/exec'),
  2. channel = require('cordova/channel'),
  3. // Reference name for the plugin
  4. PLUGIN_NAME = 'HotCodePush',
  5. // Plugin methods on the native side that can be called from JavaScript
  6. pluginNativeMethod = {
  7. INITIALIZE: 'jsInitPlugin',
  8. FETCH_UPDATE: 'jsFetchUpdate',
  9. INSTALL_UPDATE: 'jsInstallUpdate',
  10. CONFIGURE: 'jsConfigure',
  11. REQUEST_APP_UPDATE: 'jsRequestAppUpdate',
  12. IS_UPDATE_AVAILABLE_FOR_INSTALLATION: 'jsIsUpdateAvailableForInstallation',
  13. GET_INFO: 'jsGetVersionInfo'
  14. };
  15. // Called when Cordova is ready for work.
  16. // Here we will send default callback to the native side through which it will send to us different events.
  17. channel.onCordovaReady.subscribe(function() {
  18. ensureCustomEventExists();
  19. exec(nativeCallback, null, PLUGIN_NAME, pluginNativeMethod.INITIALIZE, []);
  20. });
  21. /**
  22. * Method is called when native side sends us different events.
  23. * Those events can be about update download/installation process.
  24. *
  25. * @param {String} msg - JSON formatted string with call arguments
  26. */
  27. function nativeCallback(msg) {
  28. // parse call arguments
  29. var resultObj = processMessageFromNative(msg);
  30. if (resultObj.action == null) {
  31. console.log('Action is not provided, skipping');
  32. return;
  33. }
  34. broadcastEventFromNative(resultObj);
  35. }
  36. /**
  37. * Parse arguments that were sent from the native side.
  38. * Arguments are a JSON string of type:
  39. * { action: "action identifier", error: {...error data...}, data: {...some additional data..} }
  40. * Some parameters may not exist, but the resulting object will have them all.
  41. *
  42. * @param {String} msg - arguments as JSON string
  43. * @return {Object} parsed string
  44. */
  45. function processMessageFromNative(msg) {
  46. var errorContent = null,
  47. dataContent = null,
  48. actionId = null;
  49. try {
  50. var resultObj = JSON.parse(msg);
  51. if (resultObj.hasOwnProperty('error')) {
  52. errorContent = resultObj.error;
  53. }
  54. if (resultObj.hasOwnProperty('data')) {
  55. dataContent = resultObj.data;
  56. }
  57. if (resultObj.hasOwnProperty('action')) {
  58. actionId = resultObj.action;
  59. }
  60. } catch (err) {}
  61. return {
  62. action: actionId,
  63. error: errorContent,
  64. data: dataContent
  65. };
  66. }
  67. function callNativeMethod(methodName, options, callback) {
  68. var innerCallback = function(msg) {
  69. var resultObj = processMessageFromNative(msg);
  70. if (callback !== undefined && callback != null) {
  71. callback(resultObj.error, resultObj.data);
  72. }
  73. };
  74. var sendArgs = [];
  75. if (options !== null && options !== undefined) {
  76. sendArgs.push(options);
  77. }
  78. exec(innerCallback, null, PLUGIN_NAME, methodName, sendArgs);
  79. }
  80. // region Update/Install events
  81. /*
  82. * Polyfill for adding CustomEvent which may not exist on older versions of Android.
  83. * See https://developer.mozilla.org/fr/docs/Web/API/CustomEvent for more details.
  84. */
  85. function ensureCustomEventExists() {
  86. // Create only if it doesn't exist
  87. if (window.CustomEvent) {
  88. return;
  89. }
  90. var CustomEvent = function(event, params) {
  91. params = params || {
  92. bubbles: false,
  93. cancelable: false,
  94. detail: undefined
  95. };
  96. var evt = document.createEvent('CustomEvent');
  97. evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
  98. return evt;
  99. };
  100. CustomEvent.prototype = window.Event.prototype;
  101. window.CustomEvent = CustomEvent;
  102. }
  103. /**
  104. * Broadcast event that was received from the native side.
  105. *
  106. * @param {Object} arguments, received from the native side
  107. */
  108. function broadcastEventFromNative(nativeMessage) {
  109. var params = {};
  110. if (nativeMessage.error != null) {
  111. params.error = nativeMessage.error;
  112. }
  113. var chcpEvent = new CustomEvent(nativeMessage.action, {
  114. 'detail': params
  115. });
  116. document.dispatchEvent(chcpEvent);
  117. }
  118. // endregion
  119. /**
  120. * Public module of the plugin.
  121. * May be used by developers to send commands to the plugin.
  122. */
  123. var chcp = {
  124. // Plugin error codes
  125. error: {
  126. NOTHING_TO_INSTALL: 1,
  127. NOTHING_TO_UPDATE: 2,
  128. FAILED_TO_DOWNLOAD_APPLICATION_CONFIG: -1,
  129. APPLICATION_BUILD_VERSION_TOO_LOW: -2,
  130. FAILED_TO_DOWNLOAD_CONTENT_MANIFEST: -3,
  131. FAILED_TO_DOWNLOAD_UPDATE_FILES: -4,
  132. FAILED_TO_MOVE_LOADED_FILES_TO_INSTALLATION_FOLDER: -5,
  133. UPDATE_IS_INVALID: -6,
  134. FAILED_TO_COPY_FILES_FROM_PREVIOUS_RELEASE: -7,
  135. FAILED_TO_COPY_NEW_CONTENT_FILES: -8,
  136. LOCAL_VERSION_OF_APPLICATION_CONFIG_NOT_FOUND: -9,
  137. LOCAL_VERSION_OF_MANIFEST_NOT_FOUND: -10,
  138. LOADED_VERSION_OF_APPLICATION_CONFIG_NOT_FOUND: -11,
  139. LOADED_VERSION_OF_MANIFEST_NOT_FOUND: -12,
  140. FAILED_TO_INSTALL_ASSETS_ON_EXTERNAL_STORAGE: -13,
  141. CANT_INSTALL_WHILE_DOWNLOAD_IN_PROGRESS: -14,
  142. CANT_DOWNLOAD_UPDATE_WHILE_INSTALLATION_IN_PROGRESS: -15,
  143. INSTALLATION_ALREADY_IN_PROGRESS: -16,
  144. DOWNLOAD_ALREADY_IN_PROGRESS: -17,
  145. ASSETS_FOLDER_IN_NOT_YET_INSTALLED: -18,
  146. NEW_APPLICATION_CONFIG_IS_INVALID: -19
  147. },
  148. // Plugin events
  149. event: {
  150. BEFORE_ASSETS_INSTALLATION: 'chcp_beforeAssetsInstalledOnExternalStorage',
  151. ASSETS_INSTALLATION_FAILED: 'chcp_assetsInstallationError',
  152. ASSETS_INSTALLED: 'chcp_assetsInstalledOnExternalStorage',
  153. NOTHING_TO_UPDATE: 'chcp_nothingToUpdate',
  154. UPDATE_LOAD_FAILED: 'chcp_updateLoadFailed',
  155. UPDATE_IS_READY_TO_INSTALL: 'chcp_updateIsReadyToInstall',
  156. BEFORE_UPDATE_INSTALLATION: 'chcp_beforeInstall',
  157. UPDATE_INSTALLATION_FAILED: 'chcp_updateInstallFailed',
  158. UPDATE_INSTALLED: 'chcp_updateInstalled',
  159. NOTHING_TO_INSTALL: 'chcp_nothingToInstall'
  160. },
  161. /**
  162. * DEPRECATED! WILL BE REMOVED EVENTUALLY!
  163. *
  164. * If you want to set config-url - use chcp.fetchUpdate(callback, options).
  165. * If you want to set auto-download/auto-install preference - do it in config.xml instead of this method.
  166. *
  167. * Set plugin options.
  168. * Options are send to the native side.
  169. * As soon as they are processed - callback is called.
  170. *
  171. * @param {Object} options - options to set
  172. * @param {Callback(error)} callback - callback to call when options are set
  173. */
  174. configure: function(options, callback) {
  175. if (options === undefined || options == null) {
  176. return;
  177. }
  178. callNativeMethod(pluginNativeMethod.CONFIGURE, options, callback);
  179. },
  180. /**
  181. * Show dialog with the request to update application through the Store (App Store or Google Play).
  182. * For that purpose you can use any other cordova library, this is just a small helper method.
  183. *
  184. * @param {String} message - message to show in the dialog
  185. * @param {Callback()} onStoreOpenCallback - called when user redirects to the Store
  186. * @param {Callback()} onUserDismissedDialogCallback - called when user declines to go to the Store
  187. */
  188. requestApplicationUpdate: function(message, onStoreOpenCallback, onUserDismissedDialogCallback) {
  189. if (message == undefined || message.length == 0) {
  190. return;
  191. }
  192. var onSuccessInnerCallback = function(msg) {
  193. if (onStoreOpenCallback) {
  194. onStoreOpenCallback();
  195. }
  196. };
  197. var onFailureInnerCallback = function(msg) {
  198. if (onUserDismissedDialogCallback) {
  199. onUserDismissedDialogCallback();
  200. }
  201. };
  202. exec(onSuccessInnerCallback, onFailureInnerCallback, PLUGIN_NAME, pluginNativeMethod.REQUEST_APP_UPDATE, [message]);
  203. },
  204. /**
  205. * Check if any new content is available on the server and download it.
  206. * Usually this is done automatically by the plugin, but can be triggered at any time from the web page.
  207. *
  208. * @param {Callback(error, data)} callback - called when native side finished update process
  209. * @param {Object} options - additional options, such as "config-url" and additional http headers.
  210. */
  211. fetchUpdate: function(callback, options) {
  212. callNativeMethod(pluginNativeMethod.FETCH_UPDATE, options, callback);
  213. },
  214. /**
  215. * Install update if there is anything to install.
  216. *
  217. * @param {Callback(error)} callback - called when native side finishes installation process
  218. */
  219. installUpdate: function(callback) {
  220. callNativeMethod(pluginNativeMethod.INSTALL_UPDATE, null, callback);
  221. },
  222. /**
  223. * Check if update was loaded and ready to be installed.
  224. * If update was loaded and can be installed - "data" property of the callback will contain the name of the current version and the name of the new
  225. * version.
  226. * If not - "error" will contain code chcp.error.NOTHING_TO_INSTALL.
  227. *
  228. * @param {Callback(error, data)} callback - called, when information is retrieved from the native side.
  229. */
  230. isUpdateAvailableForInstallation: function(callback) {
  231. callNativeMethod(pluginNativeMethod.IS_UPDATE_AVAILABLE_FOR_INSTALLATION, null, callback);
  232. },
  233. /**
  234. * Get information about the current version like current release version, app build version and so on.
  235. * The "data" property of the callback will contain all the information.
  236. *
  237. * @param {Callback(error, data)} callback - called, when information is retrieved from the native side.
  238. */
  239. getVersionInfo: function(callback) {
  240. callNativeMethod(pluginNativeMethod.GET_INFO, null, callback);
  241. }
  242. };
  243. module.exports = chcp;