native-bridge.js 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /*! Capacitor: https://capacitorjs.com/ - MIT License */
  2. /* Generated File. Do not edit. */
  3. var nativeBridge = (function (exports) {
  4. 'use strict';
  5. var ExceptionCode;
  6. (function (ExceptionCode) {
  7. /**
  8. * API is not implemented.
  9. *
  10. * This usually means the API can't be used because it is not implemented for
  11. * the current platform.
  12. */
  13. ExceptionCode["Unimplemented"] = "UNIMPLEMENTED";
  14. /**
  15. * API is not available.
  16. *
  17. * This means the API can't be used right now because:
  18. * - it is currently missing a prerequisite, such as network connectivity
  19. * - it requires a particular platform or browser version
  20. */
  21. ExceptionCode["Unavailable"] = "UNAVAILABLE";
  22. })(ExceptionCode || (ExceptionCode = {}));
  23. class CapacitorException extends Error {
  24. constructor(message, code, data) {
  25. super(message);
  26. this.message = message;
  27. this.code = code;
  28. this.data = data;
  29. }
  30. }
  31. // For removing exports for iOS/Android, keep let for reassignment
  32. // eslint-disable-next-line
  33. let dummy = {};
  34. const readFileAsBase64 = (file) => new Promise((resolve, reject) => {
  35. const reader = new FileReader();
  36. reader.onloadend = () => {
  37. const data = reader.result;
  38. resolve(btoa(data));
  39. };
  40. reader.onerror = reject;
  41. reader.readAsBinaryString(file);
  42. });
  43. const convertFormData = async (formData) => {
  44. const newFormData = [];
  45. for (const pair of formData.entries()) {
  46. const [key, value] = pair;
  47. if (value instanceof File) {
  48. const base64File = await readFileAsBase64(value);
  49. newFormData.push({
  50. key,
  51. value: base64File,
  52. type: 'base64File',
  53. contentType: value.type,
  54. fileName: value.name,
  55. });
  56. }
  57. else {
  58. newFormData.push({ key, value, type: 'string' });
  59. }
  60. }
  61. return newFormData;
  62. };
  63. const convertBody = async (body, contentType) => {
  64. if (body instanceof ReadableStream) {
  65. const reader = body.getReader();
  66. const chunks = [];
  67. while (true) {
  68. const { done, value } = await reader.read();
  69. if (done)
  70. break;
  71. chunks.push(value);
  72. }
  73. const concatenated = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
  74. let position = 0;
  75. for (const chunk of chunks) {
  76. concatenated.set(chunk, position);
  77. position += chunk.length;
  78. }
  79. let data = new TextDecoder().decode(concatenated);
  80. let type;
  81. if (contentType === 'application/json') {
  82. try {
  83. data = JSON.parse(data);
  84. }
  85. catch (ignored) {
  86. // ignore
  87. }
  88. type = 'json';
  89. }
  90. else if (contentType === 'multipart/form-data') {
  91. type = 'formData';
  92. }
  93. else if (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('image')) {
  94. type = 'image';
  95. }
  96. else if (contentType === 'application/octet-stream') {
  97. type = 'binary';
  98. }
  99. else {
  100. type = 'text';
  101. }
  102. return {
  103. data,
  104. type,
  105. headers: { 'Content-Type': contentType || 'application/octet-stream' },
  106. };
  107. }
  108. else if (body instanceof FormData) {
  109. const formData = await convertFormData(body);
  110. const boundary = `${Date.now()}`;
  111. return {
  112. data: formData,
  113. type: 'formData',
  114. headers: {
  115. 'Content-Type': `multipart/form-data; boundary=--${boundary}`,
  116. },
  117. };
  118. }
  119. else if (body instanceof File) {
  120. const fileData = await readFileAsBase64(body);
  121. return {
  122. data: fileData,
  123. type: 'file',
  124. headers: { 'Content-Type': body.type },
  125. };
  126. }
  127. return { data: body, type: 'json' };
  128. };
  129. const initBridge = (w) => {
  130. const getPlatformId = (win) => {
  131. var _a, _b;
  132. if (win === null || win === void 0 ? void 0 : win.androidBridge) {
  133. return 'android';
  134. }
  135. else if ((_b = (_a = win === null || win === void 0 ? void 0 : win.webkit) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b.bridge) {
  136. return 'ios';
  137. }
  138. else {
  139. return 'web';
  140. }
  141. };
  142. const convertFileSrcServerUrl = (webviewServerUrl, filePath) => {
  143. if (typeof filePath === 'string') {
  144. if (filePath.startsWith('/')) {
  145. return webviewServerUrl + '/_capacitor_file_' + filePath;
  146. }
  147. else if (filePath.startsWith('file://')) {
  148. return (webviewServerUrl + filePath.replace('file://', '/_capacitor_file_'));
  149. }
  150. else if (filePath.startsWith('content://')) {
  151. return (webviewServerUrl +
  152. filePath.replace('content:/', '/_capacitor_content_'));
  153. }
  154. }
  155. return filePath;
  156. };
  157. const initEvents = (win, cap) => {
  158. cap.addListener = (pluginName, eventName, callback) => {
  159. const callbackId = cap.nativeCallback(pluginName, 'addListener', {
  160. eventName: eventName,
  161. }, callback);
  162. return {
  163. remove: async () => {
  164. var _a;
  165. (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.debug('Removing listener', pluginName, eventName);
  166. cap.removeListener(pluginName, callbackId, eventName, callback);
  167. },
  168. };
  169. };
  170. cap.removeListener = (pluginName, callbackId, eventName, callback) => {
  171. cap.nativeCallback(pluginName, 'removeListener', {
  172. callbackId: callbackId,
  173. eventName: eventName,
  174. }, callback);
  175. };
  176. cap.createEvent = (eventName, eventData) => {
  177. const doc = win.document;
  178. if (doc) {
  179. const ev = doc.createEvent('Events');
  180. ev.initEvent(eventName, false, false);
  181. if (eventData && typeof eventData === 'object') {
  182. for (const i in eventData) {
  183. // eslint-disable-next-line no-prototype-builtins
  184. if (eventData.hasOwnProperty(i)) {
  185. ev[i] = eventData[i];
  186. }
  187. }
  188. }
  189. return ev;
  190. }
  191. return null;
  192. };
  193. cap.triggerEvent = (eventName, target, eventData) => {
  194. const doc = win.document;
  195. const cordova = win.cordova;
  196. eventData = eventData || {};
  197. const ev = cap.createEvent(eventName, eventData);
  198. if (ev) {
  199. if (target === 'document') {
  200. if (cordova === null || cordova === void 0 ? void 0 : cordova.fireDocumentEvent) {
  201. cordova.fireDocumentEvent(eventName, eventData);
  202. return true;
  203. }
  204. else if (doc === null || doc === void 0 ? void 0 : doc.dispatchEvent) {
  205. return doc.dispatchEvent(ev);
  206. }
  207. }
  208. else if (target === 'window' && win.dispatchEvent) {
  209. return win.dispatchEvent(ev);
  210. }
  211. else if (doc === null || doc === void 0 ? void 0 : doc.querySelector) {
  212. const targetEl = doc.querySelector(target);
  213. if (targetEl) {
  214. return targetEl.dispatchEvent(ev);
  215. }
  216. }
  217. }
  218. return false;
  219. };
  220. win.Capacitor = cap;
  221. };
  222. const initLegacyHandlers = (win, cap) => {
  223. // define cordova if it's not there already
  224. win.cordova = win.cordova || {};
  225. const doc = win.document;
  226. const nav = win.navigator;
  227. if (nav) {
  228. nav.app = nav.app || {};
  229. nav.app.exitApp = () => {
  230. var _a;
  231. if (!((_a = cap.Plugins) === null || _a === void 0 ? void 0 : _a.App)) {
  232. win.console.warn('App plugin not installed');
  233. }
  234. else {
  235. cap.nativeCallback('App', 'exitApp', {});
  236. }
  237. };
  238. }
  239. if (doc) {
  240. const docAddEventListener = doc.addEventListener;
  241. doc.addEventListener = (...args) => {
  242. var _a;
  243. const eventName = args[0];
  244. const handler = args[1];
  245. if (eventName === 'deviceready' && handler) {
  246. Promise.resolve().then(handler);
  247. }
  248. else if (eventName === 'backbutton' && cap.Plugins.App) {
  249. // Add a dummy listener so Capacitor doesn't do the default
  250. // back button action
  251. if (!((_a = cap.Plugins) === null || _a === void 0 ? void 0 : _a.App)) {
  252. win.console.warn('App plugin not installed');
  253. }
  254. else {
  255. cap.Plugins.App.addListener('backButton', () => {
  256. // ignore
  257. });
  258. }
  259. }
  260. return docAddEventListener.apply(doc, args);
  261. };
  262. }
  263. // deprecated in v3, remove from v4
  264. cap.platform = cap.getPlatform();
  265. cap.isNative = cap.isNativePlatform();
  266. win.Capacitor = cap;
  267. };
  268. const initVendor = (win, cap) => {
  269. const Ionic = (win.Ionic = win.Ionic || {});
  270. const IonicWebView = (Ionic.WebView = Ionic.WebView || {});
  271. const Plugins = cap.Plugins;
  272. IonicWebView.getServerBasePath = (callback) => {
  273. var _a;
  274. (_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.getServerBasePath().then((result) => {
  275. callback(result.path);
  276. });
  277. };
  278. IonicWebView.setServerBasePath = (path) => {
  279. var _a;
  280. (_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.setServerBasePath({ path });
  281. };
  282. IonicWebView.persistServerBasePath = () => {
  283. var _a;
  284. (_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.persistServerBasePath();
  285. };
  286. IonicWebView.convertFileSrc = (url) => cap.convertFileSrc(url);
  287. win.Capacitor = cap;
  288. win.Ionic.WebView = IonicWebView;
  289. };
  290. const initLogger = (win, cap) => {
  291. const BRIDGED_CONSOLE_METHODS = [
  292. 'debug',
  293. 'error',
  294. 'info',
  295. 'log',
  296. 'trace',
  297. 'warn',
  298. ];
  299. const createLogFromNative = (c) => (result) => {
  300. if (isFullConsole(c)) {
  301. const success = result.success === true;
  302. const tagStyles = success
  303. ? 'font-style: italic; font-weight: lighter; color: gray'
  304. : 'font-style: italic; font-weight: lighter; color: red';
  305. c.groupCollapsed('%cresult %c' +
  306. result.pluginId +
  307. '.' +
  308. result.methodName +
  309. ' (#' +
  310. result.callbackId +
  311. ')', tagStyles, 'font-style: italic; font-weight: bold; color: #444');
  312. if (result.success === false) {
  313. c.error(result.error);
  314. }
  315. else {
  316. c.dir(result.data);
  317. }
  318. c.groupEnd();
  319. }
  320. else {
  321. if (result.success === false) {
  322. c.error('LOG FROM NATIVE', result.error);
  323. }
  324. else {
  325. c.log('LOG FROM NATIVE', result.data);
  326. }
  327. }
  328. };
  329. const createLogToNative = (c) => (call) => {
  330. if (isFullConsole(c)) {
  331. c.groupCollapsed('%cnative %c' +
  332. call.pluginId +
  333. '.' +
  334. call.methodName +
  335. ' (#' +
  336. call.callbackId +
  337. ')', 'font-weight: lighter; color: gray', 'font-weight: bold; color: #000');
  338. c.dir(call);
  339. c.groupEnd();
  340. }
  341. else {
  342. c.log('LOG TO NATIVE: ', call);
  343. }
  344. };
  345. const isFullConsole = (c) => {
  346. if (!c) {
  347. return false;
  348. }
  349. return (typeof c.groupCollapsed === 'function' ||
  350. typeof c.groupEnd === 'function' ||
  351. typeof c.dir === 'function');
  352. };
  353. const serializeConsoleMessage = (msg) => {
  354. if (typeof msg === 'object') {
  355. try {
  356. msg = JSON.stringify(msg);
  357. }
  358. catch (e) {
  359. // ignore
  360. }
  361. }
  362. return String(msg);
  363. };
  364. const platform = getPlatformId(win);
  365. if (platform == 'android' || platform == 'ios') {
  366. // patch document.cookie on Android/iOS
  367. win.CapacitorCookiesDescriptor =
  368. Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
  369. Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
  370. let doPatchCookies = false;
  371. // check if capacitor cookies is disabled before patching
  372. if (platform === 'ios') {
  373. // Use prompt to synchronously get capacitor cookies config.
  374. // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
  375. const payload = {
  376. type: 'CapacitorCookies.isEnabled',
  377. };
  378. const isCookiesEnabled = prompt(JSON.stringify(payload));
  379. if (isCookiesEnabled === 'true') {
  380. doPatchCookies = true;
  381. }
  382. }
  383. else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
  384. const isCookiesEnabled = win.CapacitorCookiesAndroidInterface.isEnabled();
  385. if (isCookiesEnabled === true) {
  386. doPatchCookies = true;
  387. }
  388. }
  389. if (doPatchCookies) {
  390. Object.defineProperty(document, 'cookie', {
  391. get: function () {
  392. var _a, _b, _c;
  393. if (platform === 'ios') {
  394. // Use prompt to synchronously get cookies.
  395. // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
  396. const payload = {
  397. type: 'CapacitorCookies.get',
  398. };
  399. const res = prompt(JSON.stringify(payload));
  400. return res;
  401. }
  402. else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
  403. // return original document.cookie since Android does not support filtering of `httpOnly` cookies
  404. return (_c = (_b = (_a = win.CapacitorCookiesDescriptor) === null || _a === void 0 ? void 0 : _a.get) === null || _b === void 0 ? void 0 : _b.call(document)) !== null && _c !== void 0 ? _c : '';
  405. }
  406. },
  407. set: function (val) {
  408. const cookiePairs = val.split(';');
  409. const domainSection = val.toLowerCase().split('domain=')[1];
  410. const domain = cookiePairs.length > 1 &&
  411. domainSection != null &&
  412. domainSection.length > 0
  413. ? domainSection.split(';')[0].trim()
  414. : '';
  415. if (platform === 'ios') {
  416. // Use prompt to synchronously set cookies.
  417. // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
  418. const payload = {
  419. type: 'CapacitorCookies.set',
  420. action: val,
  421. domain,
  422. };
  423. prompt(JSON.stringify(payload));
  424. }
  425. else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
  426. win.CapacitorCookiesAndroidInterface.setCookie(domain, val);
  427. }
  428. },
  429. });
  430. }
  431. // patch fetch / XHR on Android/iOS
  432. // store original fetch & XHR functions
  433. win.CapacitorWebFetch = window.fetch;
  434. win.CapacitorWebXMLHttpRequest = {
  435. abort: window.XMLHttpRequest.prototype.abort,
  436. constructor: window.XMLHttpRequest.prototype.constructor,
  437. fullObject: window.XMLHttpRequest,
  438. getAllResponseHeaders: window.XMLHttpRequest.prototype.getAllResponseHeaders,
  439. getResponseHeader: window.XMLHttpRequest.prototype.getResponseHeader,
  440. open: window.XMLHttpRequest.prototype.open,
  441. prototype: window.XMLHttpRequest.prototype,
  442. send: window.XMLHttpRequest.prototype.send,
  443. setRequestHeader: window.XMLHttpRequest.prototype.setRequestHeader,
  444. };
  445. let doPatchHttp = false;
  446. // check if capacitor http is disabled before patching
  447. if (platform === 'ios') {
  448. // Use prompt to synchronously get capacitor http config.
  449. // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
  450. const payload = {
  451. type: 'CapacitorHttp',
  452. };
  453. const isHttpEnabled = prompt(JSON.stringify(payload));
  454. if (isHttpEnabled === 'true') {
  455. doPatchHttp = true;
  456. }
  457. }
  458. else if (typeof win.CapacitorHttpAndroidInterface !== 'undefined') {
  459. const isHttpEnabled = win.CapacitorHttpAndroidInterface.isEnabled();
  460. if (isHttpEnabled === true) {
  461. doPatchHttp = true;
  462. }
  463. }
  464. if (doPatchHttp) {
  465. // fetch patch
  466. window.fetch = async (resource, options) => {
  467. const request = new Request(resource, options);
  468. if (request.url.startsWith(`${cap.getServerUrl()}/`)) {
  469. return win.CapacitorWebFetch(resource, options);
  470. }
  471. const tag = `CapacitorHttp fetch ${Date.now()} ${resource}`;
  472. console.time(tag);
  473. try {
  474. // intercept request & pass to the bridge
  475. const { body, method } = request;
  476. const optionHeaders = Object.fromEntries(request.headers.entries());
  477. const { data: requestData, type, headers, } = await convertBody((options === null || options === void 0 ? void 0 : options.body) || body || undefined, optionHeaders['Content-Type'] || optionHeaders['content-type']);
  478. const nativeResponse = await cap.nativePromise('CapacitorHttp', 'request', {
  479. url: request.url,
  480. method: method,
  481. data: requestData,
  482. dataType: type,
  483. headers: Object.assign(Object.assign({}, headers), optionHeaders),
  484. });
  485. const contentType = nativeResponse.headers['Content-Type'] ||
  486. nativeResponse.headers['content-type'];
  487. let data = (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('application/json'))
  488. ? JSON.stringify(nativeResponse.data)
  489. : nativeResponse.data;
  490. // use null data for 204 No Content HTTP response
  491. if (nativeResponse.status === 204) {
  492. data = null;
  493. }
  494. // intercept & parse response before returning
  495. const response = new Response(data, {
  496. headers: nativeResponse.headers,
  497. status: nativeResponse.status,
  498. });
  499. /*
  500. * copy url to response, `cordova-plugin-ionic` uses this url from the response
  501. * we need `Object.defineProperty` because url is an inherited getter on the Response
  502. * see: https://stackoverflow.com/a/57382543
  503. * */
  504. Object.defineProperty(response, 'url', {
  505. value: nativeResponse.url,
  506. });
  507. console.timeEnd(tag);
  508. return response;
  509. }
  510. catch (error) {
  511. console.timeEnd(tag);
  512. return Promise.reject(error);
  513. }
  514. };
  515. window.XMLHttpRequest = function () {
  516. const xhr = new win.CapacitorWebXMLHttpRequest.constructor();
  517. Object.defineProperties(xhr, {
  518. _headers: {
  519. value: {},
  520. writable: true,
  521. },
  522. _method: {
  523. value: xhr.method,
  524. writable: true,
  525. },
  526. readyState: {
  527. get: function () {
  528. var _a;
  529. return (_a = this._readyState) !== null && _a !== void 0 ? _a : 0;
  530. },
  531. set: function (val) {
  532. this._readyState = val;
  533. setTimeout(() => {
  534. this.dispatchEvent(new Event('readystatechange'));
  535. });
  536. },
  537. },
  538. });
  539. xhr.readyState = 0;
  540. const prototype = win.CapacitorWebXMLHttpRequest.prototype;
  541. const isRelativeURL = (url) => !url || !(url.startsWith('http:') || url.startsWith('https:'));
  542. const isProgressEventAvailable = () => typeof ProgressEvent !== 'undefined' &&
  543. ProgressEvent.prototype instanceof Event;
  544. // XHR patch abort
  545. prototype.abort = function () {
  546. if (isRelativeURL(this._url)) {
  547. return win.CapacitorWebXMLHttpRequest.abort.call(this);
  548. }
  549. this.readyState = 0;
  550. setTimeout(() => {
  551. this.dispatchEvent(new Event('abort'));
  552. this.dispatchEvent(new Event('loadend'));
  553. });
  554. };
  555. // XHR patch open
  556. prototype.open = function (method, url) {
  557. this._url = url;
  558. this._method = method;
  559. if (isRelativeURL(url)) {
  560. return win.CapacitorWebXMLHttpRequest.open.call(this, method, url);
  561. }
  562. setTimeout(() => {
  563. this.dispatchEvent(new Event('loadstart'));
  564. });
  565. this.readyState = 1;
  566. };
  567. // XHR patch set request header
  568. prototype.setRequestHeader = function (header, value) {
  569. if (isRelativeURL(this._url)) {
  570. return win.CapacitorWebXMLHttpRequest.setRequestHeader.call(this, header, value);
  571. }
  572. this._headers[header] = value;
  573. };
  574. // XHR patch send
  575. prototype.send = function (body) {
  576. if (isRelativeURL(this._url)) {
  577. return win.CapacitorWebXMLHttpRequest.send.call(this, body);
  578. }
  579. const tag = `CapacitorHttp XMLHttpRequest ${Date.now()} ${this._url}`;
  580. console.time(tag);
  581. try {
  582. this.readyState = 2;
  583. Object.defineProperties(this, {
  584. response: {
  585. value: '',
  586. writable: true,
  587. },
  588. responseText: {
  589. value: '',
  590. writable: true,
  591. },
  592. responseURL: {
  593. value: '',
  594. writable: true,
  595. },
  596. status: {
  597. value: 0,
  598. writable: true,
  599. },
  600. });
  601. convertBody(body).then(({ data, type, headers }) => {
  602. const otherHeaders = this._headers != null && Object.keys(this._headers).length > 0
  603. ? this._headers
  604. : undefined;
  605. // intercept request & pass to the bridge
  606. cap
  607. .nativePromise('CapacitorHttp', 'request', {
  608. url: this._url,
  609. method: this._method,
  610. data: data !== null ? data : undefined,
  611. headers: Object.assign(Object.assign({}, headers), otherHeaders),
  612. dataType: type,
  613. })
  614. .then((nativeResponse) => {
  615. var _a;
  616. // intercept & parse response before returning
  617. if (this.readyState == 2) {
  618. //TODO: Add progress event emission on native side
  619. if (isProgressEventAvailable()) {
  620. this.dispatchEvent(new ProgressEvent('progress', {
  621. lengthComputable: true,
  622. loaded: nativeResponse.data.length,
  623. total: nativeResponse.data.length,
  624. }));
  625. }
  626. this._headers = nativeResponse.headers;
  627. this.status = nativeResponse.status;
  628. const responseString = typeof nativeResponse.data !== 'string'
  629. ? JSON.stringify(nativeResponse.data)
  630. : nativeResponse.data;
  631. if (this.responseType === '' ||
  632. this.responseType === 'text') {
  633. this.response = responseString;
  634. }
  635. else if (this.responseType === 'blob') {
  636. this.response = new Blob([responseString], {
  637. type: 'application/json',
  638. });
  639. }
  640. else if (this.responseType === 'arraybuffer') {
  641. const encoder = new TextEncoder();
  642. const uint8Array = encoder.encode(responseString);
  643. this.response = uint8Array.buffer;
  644. }
  645. else {
  646. this.response = nativeResponse.data;
  647. }
  648. this.responseText = ((_a = nativeResponse.headers['Content-Type']) === null || _a === void 0 ? void 0 : _a.startsWith('application/json'))
  649. ? JSON.stringify(nativeResponse.data)
  650. : nativeResponse.data;
  651. this.responseURL = nativeResponse.url;
  652. this.readyState = 4;
  653. setTimeout(() => {
  654. this.dispatchEvent(new Event('load'));
  655. this.dispatchEvent(new Event('loadend'));
  656. });
  657. }
  658. console.timeEnd(tag);
  659. })
  660. .catch((error) => {
  661. this.status = error.status;
  662. this._headers = error.headers;
  663. this.response = error.data;
  664. this.responseText = JSON.stringify(error.data);
  665. this.responseURL = error.url;
  666. this.readyState = 4;
  667. if (isProgressEventAvailable()) {
  668. this.dispatchEvent(new ProgressEvent('progress', {
  669. lengthComputable: false,
  670. loaded: 0,
  671. total: 0,
  672. }));
  673. }
  674. setTimeout(() => {
  675. this.dispatchEvent(new Event('error'));
  676. this.dispatchEvent(new Event('loadend'));
  677. });
  678. console.timeEnd(tag);
  679. });
  680. });
  681. }
  682. catch (error) {
  683. this.status = 500;
  684. this._headers = {};
  685. this.response = error;
  686. this.responseText = error.toString();
  687. this.responseURL = this._url;
  688. this.readyState = 4;
  689. if (isProgressEventAvailable()) {
  690. this.dispatchEvent(new ProgressEvent('progress', {
  691. lengthComputable: false,
  692. loaded: 0,
  693. total: 0,
  694. }));
  695. }
  696. setTimeout(() => {
  697. this.dispatchEvent(new Event('error'));
  698. this.dispatchEvent(new Event('loadend'));
  699. });
  700. console.timeEnd(tag);
  701. }
  702. };
  703. // XHR patch getAllResponseHeaders
  704. prototype.getAllResponseHeaders = function () {
  705. if (isRelativeURL(this._url)) {
  706. return win.CapacitorWebXMLHttpRequest.getAllResponseHeaders.call(this);
  707. }
  708. let returnString = '';
  709. for (const key in this._headers) {
  710. if (key.toLowerCase() !== 'set-cookie') {
  711. returnString += key + ': ' + this._headers[key] + '\r\n';
  712. }
  713. }
  714. return returnString;
  715. };
  716. // XHR patch getResponseHeader
  717. prototype.getResponseHeader = function (name) {
  718. if (isRelativeURL(this._url)) {
  719. return win.CapacitorWebXMLHttpRequest.getResponseHeader.call(this, name);
  720. }
  721. for (const key in this._headers) {
  722. if (key.toLowerCase() === name.toLowerCase()) {
  723. return this._headers[key];
  724. }
  725. }
  726. return null;
  727. };
  728. Object.setPrototypeOf(xhr, prototype);
  729. return xhr;
  730. };
  731. Object.assign(window.XMLHttpRequest, win.CapacitorWebXMLHttpRequest.fullObject);
  732. }
  733. }
  734. // patch window.console on iOS and store original console fns
  735. const isIos = getPlatformId(win) === 'ios';
  736. if (win.console && isIos) {
  737. Object.defineProperties(win.console, BRIDGED_CONSOLE_METHODS.reduce((props, method) => {
  738. const consoleMethod = win.console[method].bind(win.console);
  739. props[method] = {
  740. value: (...args) => {
  741. const msgs = [...args];
  742. cap.toNative('Console', 'log', {
  743. level: method,
  744. message: msgs.map(serializeConsoleMessage).join(' '),
  745. });
  746. return consoleMethod(...args);
  747. },
  748. };
  749. return props;
  750. }, {}));
  751. }
  752. cap.logJs = (msg, level) => {
  753. switch (level) {
  754. case 'error':
  755. win.console.error(msg);
  756. break;
  757. case 'warn':
  758. win.console.warn(msg);
  759. break;
  760. case 'info':
  761. win.console.info(msg);
  762. break;
  763. default:
  764. win.console.log(msg);
  765. }
  766. };
  767. cap.logToNative = createLogToNative(win.console);
  768. cap.logFromNative = createLogFromNative(win.console);
  769. cap.handleError = err => win.console.error(err);
  770. win.Capacitor = cap;
  771. };
  772. function initNativeBridge(win) {
  773. const cap = win.Capacitor || {};
  774. // keep a collection of callbacks for native response data
  775. const callbacks = new Map();
  776. const webviewServerUrl = typeof win.WEBVIEW_SERVER_URL === 'string' ? win.WEBVIEW_SERVER_URL : '';
  777. cap.getServerUrl = () => webviewServerUrl;
  778. cap.convertFileSrc = filePath => convertFileSrcServerUrl(webviewServerUrl, filePath);
  779. // Counter of callback ids, randomized to avoid
  780. // any issues during reloads if a call comes back with
  781. // an existing callback id from an old session
  782. let callbackIdCount = Math.floor(Math.random() * 134217728);
  783. let postToNative = null;
  784. const isNativePlatform = () => true;
  785. const getPlatform = () => getPlatformId(win);
  786. cap.getPlatform = getPlatform;
  787. cap.isPluginAvailable = name => Object.prototype.hasOwnProperty.call(cap.Plugins, name);
  788. cap.isNativePlatform = isNativePlatform;
  789. // create the postToNative() fn if needed
  790. if (getPlatformId(win) === 'android') {
  791. // android platform
  792. postToNative = data => {
  793. var _a;
  794. try {
  795. win.androidBridge.postMessage(JSON.stringify(data));
  796. }
  797. catch (e) {
  798. (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.error(e);
  799. }
  800. };
  801. }
  802. else if (getPlatformId(win) === 'ios') {
  803. // ios platform
  804. postToNative = data => {
  805. var _a;
  806. try {
  807. data.type = data.type ? data.type : 'message';
  808. win.webkit.messageHandlers.bridge.postMessage(data);
  809. }
  810. catch (e) {
  811. (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.error(e);
  812. }
  813. };
  814. }
  815. cap.handleWindowError = (msg, url, lineNo, columnNo, err) => {
  816. const str = msg.toLowerCase();
  817. if (str.indexOf('script error') > -1) ;
  818. else {
  819. const errObj = {
  820. type: 'js.error',
  821. error: {
  822. message: msg,
  823. url: url,
  824. line: lineNo,
  825. col: columnNo,
  826. errorObject: JSON.stringify(err),
  827. },
  828. };
  829. if (err !== null) {
  830. cap.handleError(err);
  831. }
  832. postToNative(errObj);
  833. }
  834. return false;
  835. };
  836. if (cap.DEBUG) {
  837. window.onerror = cap.handleWindowError;
  838. }
  839. initLogger(win, cap);
  840. /**
  841. * Send a plugin method call to the native layer
  842. */
  843. cap.toNative = (pluginName, methodName, options, storedCallback) => {
  844. var _a, _b;
  845. try {
  846. if (typeof postToNative === 'function') {
  847. let callbackId = '-1';
  848. if (storedCallback &&
  849. (typeof storedCallback.callback === 'function' ||
  850. typeof storedCallback.resolve === 'function')) {
  851. // store the call for later lookup
  852. callbackId = String(++callbackIdCount);
  853. callbacks.set(callbackId, storedCallback);
  854. }
  855. const callData = {
  856. callbackId: callbackId,
  857. pluginId: pluginName,
  858. methodName: methodName,
  859. options: options || {},
  860. };
  861. if (cap.isLoggingEnabled && pluginName !== 'Console') {
  862. cap.logToNative(callData);
  863. }
  864. // post the call data to native
  865. postToNative(callData);
  866. return callbackId;
  867. }
  868. else {
  869. (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.warn(`implementation unavailable for: ${pluginName}`);
  870. }
  871. }
  872. catch (e) {
  873. (_b = win === null || win === void 0 ? void 0 : win.console) === null || _b === void 0 ? void 0 : _b.error(e);
  874. }
  875. return null;
  876. };
  877. if (win === null || win === void 0 ? void 0 : win.androidBridge) {
  878. win.androidBridge.onmessage = function (event) {
  879. returnResult(JSON.parse(event.data));
  880. };
  881. }
  882. /**
  883. * Process a response from the native layer.
  884. */
  885. cap.fromNative = result => {
  886. returnResult(result);
  887. };
  888. const returnResult = (result) => {
  889. var _a, _b;
  890. if (cap.isLoggingEnabled && result.pluginId !== 'Console') {
  891. cap.logFromNative(result);
  892. }
  893. // get the stored call, if it exists
  894. try {
  895. const storedCall = callbacks.get(result.callbackId);
  896. if (storedCall) {
  897. // looks like we've got a stored call
  898. if (result.error) {
  899. // ensure stacktraces by copying error properties to an Error
  900. result.error = Object.keys(result.error).reduce((err, key) => {
  901. // use any type to avoid importing util and compiling most of .ts files
  902. err[key] = result.error[key];
  903. return err;
  904. }, new cap.Exception(''));
  905. }
  906. if (typeof storedCall.callback === 'function') {
  907. // callback
  908. if (result.success) {
  909. storedCall.callback(result.data);
  910. }
  911. else {
  912. storedCall.callback(null, result.error);
  913. }
  914. }
  915. else if (typeof storedCall.resolve === 'function') {
  916. // promise
  917. if (result.success) {
  918. storedCall.resolve(result.data);
  919. }
  920. else {
  921. storedCall.reject(result.error);
  922. }
  923. // no need to keep this stored callback
  924. // around for a one time resolve promise
  925. callbacks.delete(result.callbackId);
  926. }
  927. }
  928. else if (!result.success && result.error) {
  929. // no stored callback, but if there was an error let's log it
  930. (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.warn(result.error);
  931. }
  932. if (result.save === false) {
  933. callbacks.delete(result.callbackId);
  934. }
  935. }
  936. catch (e) {
  937. (_b = win === null || win === void 0 ? void 0 : win.console) === null || _b === void 0 ? void 0 : _b.error(e);
  938. }
  939. // always delete to prevent memory leaks
  940. // overkill but we're not sure what apps will do with this data
  941. delete result.data;
  942. delete result.error;
  943. };
  944. cap.nativeCallback = (pluginName, methodName, options, callback) => {
  945. if (typeof options === 'function') {
  946. console.warn(`Using a callback as the 'options' parameter of 'nativeCallback()' is deprecated.`);
  947. callback = options;
  948. options = null;
  949. }
  950. return cap.toNative(pluginName, methodName, options, { callback });
  951. };
  952. cap.nativePromise = (pluginName, methodName, options) => {
  953. return new Promise((resolve, reject) => {
  954. cap.toNative(pluginName, methodName, options, {
  955. resolve: resolve,
  956. reject: reject,
  957. });
  958. });
  959. };
  960. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  961. cap.withPlugin = (_pluginId, _fn) => dummy;
  962. cap.Exception = CapacitorException;
  963. initEvents(win, cap);
  964. initLegacyHandlers(win, cap);
  965. initVendor(win, cap);
  966. win.Capacitor = cap;
  967. }
  968. initNativeBridge(w);
  969. };
  970. initBridge(typeof globalThis !== 'undefined'
  971. ? globalThis
  972. : typeof self !== 'undefined'
  973. ? self
  974. : typeof window !== 'undefined'
  975. ? window
  976. : typeof global !== 'undefined'
  977. ? global
  978. : {});
  979. dummy = initBridge;
  980. Object.defineProperty(exports, '__esModule', { value: true });
  981. return exports;
  982. })({});