MacUpdater.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.MacUpdater = void 0;
  6. function _bluebirdLst() {
  7. const data = require("bluebird-lst");
  8. _bluebirdLst = function () {
  9. return data;
  10. };
  11. return data;
  12. }
  13. function _builderUtilRuntime() {
  14. const data = require("builder-util-runtime");
  15. _builderUtilRuntime = function () {
  16. return data;
  17. };
  18. return data;
  19. }
  20. function _http() {
  21. const data = require("http");
  22. _http = function () {
  23. return data;
  24. };
  25. return data;
  26. }
  27. function _AppUpdater() {
  28. const data = require("./AppUpdater");
  29. _AppUpdater = function () {
  30. return data;
  31. };
  32. return data;
  33. }
  34. function _main() {
  35. const data = require("./main");
  36. _main = function () {
  37. return data;
  38. };
  39. return data;
  40. }
  41. function _Provider() {
  42. const data = require("./Provider");
  43. _Provider = function () {
  44. return data;
  45. };
  46. return data;
  47. }
  48. class MacUpdater extends _AppUpdater().AppUpdater {
  49. constructor(options) {
  50. super(options);
  51. this.nativeUpdater = require("electron").autoUpdater;
  52. this.nativeUpdater.on("error", it => {
  53. this._logger.warn(it);
  54. this.emit("error", it);
  55. });
  56. this.nativeUpdater.on("update-downloaded", () => {
  57. this._logger.info(`New version ${this.updateInfo.version} has been downloaded`);
  58. this.emit(_main().UPDATE_DOWNLOADED, this.updateInfo);
  59. });
  60. }
  61. doDownloadUpdate(updateInfo, cancellationToken) {
  62. var _this = this;
  63. return (0, _bluebirdLst().coroutine)(function* () {
  64. const files = (yield _this.provider).resolveFiles(updateInfo);
  65. const zipFileInfo = (0, _Provider().findFile)(files, "zip", ["pkg", "dmg"]);
  66. if (zipFileInfo == null) {
  67. throw (0, _builderUtilRuntime().newError)(`ZIP file not provided: ${(0, _builderUtilRuntime().safeStringifyJson)(files)}`, "ERR_UPDATER_ZIP_FILE_NOT_FOUND");
  68. }
  69. const server = (0, _http().createServer)();
  70. server.on("close", () => {
  71. _this._logger.info(`Proxy server for native Squirrel.Mac is closed (was started to download ${zipFileInfo.url.href})`);
  72. });
  73. function getServerUrl() {
  74. const address = server.address();
  75. return `http://${address.address}:${address.port}`;
  76. }
  77. const requestHeaders = yield _this.computeRequestHeaders();
  78. return yield new Promise((resolve, reject) => {
  79. server.on("request", (request, response) => {
  80. const requestUrl = request.url;
  81. _this._logger.info(`${requestUrl} requested`);
  82. if (requestUrl === "/") {
  83. const data = Buffer.from(`{ "url": "${getServerUrl()}/app.zip" }`);
  84. response.writeHead(200, {
  85. "Content-Type": "application/json",
  86. "Content-Length": data.length
  87. });
  88. response.end(data);
  89. } else if (requestUrl.startsWith("/app.zip")) {
  90. const debug = _this._logger.debug;
  91. let errorOccurred = false;
  92. response.on("finish", () => {
  93. try {
  94. setImmediate(() => server.close());
  95. } finally {
  96. if (!errorOccurred) {
  97. _this.nativeUpdater.removeListener("error", reject);
  98. resolve([]);
  99. }
  100. }
  101. });
  102. if (debug != null) {
  103. debug(`app.zip requested by Squirrel.Mac, download ${zipFileInfo.url.href}`);
  104. }
  105. _this.doProxyUpdateFile(response, zipFileInfo.url.href, requestHeaders, zipFileInfo.info.sha512, cancellationToken, error => {
  106. errorOccurred = true;
  107. try {
  108. response.writeHead(500);
  109. response.end();
  110. } finally {
  111. _this.nativeUpdater.removeListener("error", reject);
  112. reject(new Error(`Cannot download "${zipFileInfo.url}": ${error}`));
  113. }
  114. });
  115. } else {
  116. _this._logger.warn(`${requestUrl} requested, but not supported`);
  117. response.writeHead(404);
  118. response.end();
  119. }
  120. });
  121. server.listen(0, "127.0.0.1", 16, () => {
  122. _this.nativeUpdater.setFeedURL(`${getServerUrl()}`, {
  123. "Cache-Control": "no-cache"
  124. });
  125. _this.nativeUpdater.once("error", reject);
  126. _this.nativeUpdater.checkForUpdates();
  127. });
  128. });
  129. })();
  130. }
  131. doProxyUpdateFile(nativeResponse, url, headers, sha512, cancellationToken, errorHandler) {
  132. const downloadRequest = this.httpExecutor.doRequest((0, _builderUtilRuntime().configureRequestOptionsFromUrl)(url, {
  133. headers
  134. }), downloadResponse => {
  135. const statusCode = downloadResponse.statusCode;
  136. if (statusCode >= 400) {
  137. this._logger.warn(`Request to ${url} failed, status code: ${statusCode}`);
  138. try {
  139. nativeResponse.writeHead(statusCode);
  140. nativeResponse.end();
  141. } finally {
  142. errorHandler(new Error(`Cannot download "${url}", status ${statusCode}: ${downloadResponse.statusMessage}`));
  143. }
  144. return;
  145. } // in tests Electron NET Api is not used, so, we have to handle redirect.
  146. const redirectUrl = (0, _builderUtilRuntime().safeGetHeader)(downloadResponse, "location");
  147. if (redirectUrl != null) {
  148. this.doProxyUpdateFile(nativeResponse, redirectUrl, headers, sha512, cancellationToken, errorHandler);
  149. return;
  150. }
  151. const nativeHeaders = {
  152. "Content-Type": "application/zip"
  153. };
  154. const streams = [];
  155. const downloadListenerCount = this.listenerCount(_main().DOWNLOAD_PROGRESS);
  156. this._logger.info(`${_main().DOWNLOAD_PROGRESS} listener count: ${downloadListenerCount}`);
  157. if (downloadListenerCount > 0) {
  158. const contentLength = (0, _builderUtilRuntime().safeGetHeader)(downloadResponse, "content-length");
  159. this._logger.info(`contentLength: ${contentLength}`);
  160. if (contentLength != null) {
  161. nativeHeaders["Content-Length"] = contentLength;
  162. streams.push(new (_builderUtilRuntime().ProgressCallbackTransform)(parseInt(contentLength, 10), cancellationToken, it => this.emit(_main().DOWNLOAD_PROGRESS, it)));
  163. }
  164. }
  165. nativeResponse.writeHead(200, nativeHeaders); // for mac only sha512 is produced (sha256 is published for windows only to preserve backward compatibility)
  166. if (sha512 != null) {
  167. // "hex" to easy migrate to new base64 encoded hash (we already produces latest-mac.yml with hex encoded hash)
  168. streams.push(new (_builderUtilRuntime().DigestTransform)(sha512, "sha512", sha512.length === 128 && !sha512.includes("+") && !sha512.includes("Z") && !sha512.includes("=") ? "hex" : "base64"));
  169. }
  170. streams.push(nativeResponse);
  171. let lastStream = downloadResponse;
  172. for (const stream of streams) {
  173. stream.on("error", errorHandler);
  174. lastStream = lastStream.pipe(stream);
  175. }
  176. });
  177. downloadRequest.on("redirect", (statusCode, method, redirectUrl) => {
  178. if (headers.Authorization != null && headers.Authorization.startsWith("token")) {
  179. const parsedNewUrl = new URL(redirectUrl);
  180. if (parsedNewUrl.hostname.endsWith(".amazonaws.com")) {
  181. delete headers.Authorization;
  182. }
  183. }
  184. this.doProxyUpdateFile(nativeResponse, redirectUrl, headers, sha512, cancellationToken, errorHandler);
  185. });
  186. downloadRequest.on("error", errorHandler);
  187. downloadRequest.end();
  188. }
  189. quitAndInstall() {
  190. this.nativeUpdater.quitAndInstall();
  191. }
  192. } exports.MacUpdater = MacUpdater;
  193. //# sourceMappingURL=MacUpdater.js.map