@capgo/inappbrowser 8.2.0 → 8.3.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,6 +45,84 @@ exports.InvisibilityMode = void 0;
45
45
  const InAppBrowser = core.registerPlugin('InAppBrowser', {
46
46
  web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.InAppBrowserWeb()),
47
47
  });
48
+ function arrayBufferToBase64(buffer) {
49
+ const bytes = new Uint8Array(buffer);
50
+ let binary = '';
51
+ for (let i = 0; i < bytes.byteLength; i++) {
52
+ binary += String.fromCharCode(bytes[i]);
53
+ }
54
+ return btoa(binary);
55
+ }
56
+ function headersToRecord(headers) {
57
+ const result = {};
58
+ headers.forEach((value, key) => {
59
+ result[key] = value;
60
+ });
61
+ return result;
62
+ }
63
+ function isProxyResponse(obj) {
64
+ return obj !== null && typeof obj === 'object' && 'status' in obj && 'headers' in obj && !(obj instanceof Response);
65
+ }
66
+ /**
67
+ * Register a handler that intercepts all HTTP/HTTPS requests from the in-app browser webview.
68
+ *
69
+ * The callback receives a {@link ProxyRequest} for every request and must return one of:
70
+ * - A {@link ProxyResponse} object (recommended — use with CapacitorHttp for CORS-free fetching)
71
+ * - A fetch `Response` object
72
+ * - `null` to let the request pass through to its original destination
73
+ *
74
+ * **Platform note (Android):** Requests initiated directly by HTML elements (`<img>`,
75
+ * `<script>`, `<link>`, `<iframe>`, etc.) are intercepted via `shouldInterceptRequest`,
76
+ * which does not expose the request body. These requests will have an empty `body` field.
77
+ * In practice this only affects direct resource loads, which are always GET. Requests made
78
+ * via `fetch()` or `XMLHttpRequest` go through the JS bridge and include the full body.
79
+ *
80
+ * @since 9.0.0
81
+ */
82
+ const addProxyHandler = (callback) => {
83
+ return InAppBrowser.addListener('proxyRequest', async (event) => {
84
+ try {
85
+ const result = await callback(event);
86
+ if (result === null) {
87
+ await InAppBrowser.handleProxyRequest({
88
+ requestId: event.requestId,
89
+ webviewId: event.webviewId,
90
+ response: null,
91
+ });
92
+ }
93
+ else if (isProxyResponse(result)) {
94
+ // ProxyResponse returned directly (e.g. from CapacitorHttp)
95
+ await InAppBrowser.handleProxyRequest({
96
+ requestId: event.requestId,
97
+ webviewId: event.webviewId,
98
+ response: result,
99
+ });
100
+ }
101
+ else {
102
+ // fetch Response object
103
+ const cloned = result.clone();
104
+ const buffer = await cloned.arrayBuffer();
105
+ const base64Body = arrayBufferToBase64(buffer);
106
+ await InAppBrowser.handleProxyRequest({
107
+ requestId: event.requestId,
108
+ webviewId: event.webviewId,
109
+ response: {
110
+ body: base64Body,
111
+ status: result.status,
112
+ headers: headersToRecord(result.headers),
113
+ },
114
+ });
115
+ }
116
+ }
117
+ catch (_e) {
118
+ await InAppBrowser.handleProxyRequest({
119
+ requestId: event.requestId,
120
+ webviewId: event.webviewId,
121
+ response: null,
122
+ });
123
+ }
124
+ });
125
+ };
48
126
 
49
127
  class InAppBrowserWeb extends core.WebPlugin {
50
128
  clearAllCookies() {
@@ -106,6 +184,10 @@ class InAppBrowserWeb extends core.WebPlugin {
106
184
  async getPluginVersion() {
107
185
  return { version: 'web' };
108
186
  }
187
+ async handleProxyRequest() {
188
+ // No-op on web
189
+ return;
190
+ }
109
191
  async updateDimensions(options) {
110
192
  console.log('updateDimensions', options);
111
193
  // Web platform doesn't support dimension control
@@ -152,4 +234,5 @@ var web = /*#__PURE__*/Object.freeze({
152
234
  });
153
235
 
154
236
  exports.InAppBrowser = InAppBrowser;
237
+ exports.addProxyHandler = addProxyHandler;
155
238
  //# sourceMappingURL=plugin.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var BackgroundColor;\n(function (BackgroundColor) {\n BackgroundColor[\"WHITE\"] = \"white\";\n BackgroundColor[\"BLACK\"] = \"black\";\n})(BackgroundColor || (BackgroundColor = {}));\nexport var ToolBarType;\n(function (ToolBarType) {\n /**\n * Shows a simple toolbar with just a close button and share button\n * @since 0.1.0\n */\n ToolBarType[\"ACTIVITY\"] = \"activity\";\n /**\n * Shows a simple toolbar with just a close button\n * @since 7.6.8\n */\n ToolBarType[\"COMPACT\"] = \"compact\";\n /**\n * Shows a full navigation toolbar with back/forward buttons\n * @since 0.1.0\n */\n ToolBarType[\"NAVIGATION\"] = \"navigation\";\n /**\n * Shows no toolbar\n * @since 0.1.0\n */\n ToolBarType[\"BLANK\"] = \"blank\";\n})(ToolBarType || (ToolBarType = {}));\nexport var InvisibilityMode;\n(function (InvisibilityMode) {\n /**\n * WebView is aware it is hidden (dimensions may be zero).\n */\n InvisibilityMode[\"AWARE\"] = \"AWARE\";\n /**\n * WebView is hidden but reports fullscreen dimensions (uses alpha=0 to remain invisible).\n */\n InvisibilityMode[\"FAKE_VISIBLE\"] = \"FAKE_VISIBLE\";\n})(InvisibilityMode || (InvisibilityMode = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst InAppBrowser = registerPlugin('InAppBrowser', {\n web: () => import('./web').then((m) => new m.InAppBrowserWeb()),\n});\nexport * from './definitions';\nexport { InAppBrowser };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class InAppBrowserWeb extends WebPlugin {\n clearAllCookies() {\n console.log('clearAllCookies');\n return Promise.resolve();\n }\n clearCache() {\n console.log('clearCache');\n return Promise.resolve();\n }\n async open(options) {\n console.log('open', options);\n return options;\n }\n async clearCookies(options) {\n console.log('cleanCookies', options);\n return;\n }\n async getCookies(options) {\n // Web implementation to get cookies\n return options;\n }\n async openWebView(options) {\n console.log('openWebView', options);\n return options;\n }\n async executeScript({ code }) {\n console.log('code', code);\n return code;\n }\n async close() {\n console.log('close');\n return;\n }\n async hide() {\n console.log('hide');\n return;\n }\n async show() {\n console.log('show');\n return;\n }\n async setUrl(options) {\n console.log('setUrl', options.url);\n return;\n }\n async reload() {\n console.log('reload');\n return;\n }\n async postMessage(options) {\n console.log('postMessage', options);\n return options;\n }\n async goBack() {\n console.log('goBack');\n return;\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n async updateDimensions(options) {\n console.log('updateDimensions', options);\n // Web platform doesn't support dimension control\n return;\n }\n async openSecureWindow(options) {\n const w = 600;\n const h = 550;\n const settings = [\n ['width', w],\n ['height', h],\n ['left', screen.width / 2 - w / 2],\n ['top', screen.height / 2 - h / 2],\n ]\n .map((x) => x.join('='))\n .join(',');\n const popup = window.open(options.authEndpoint, 'Authorization', settings);\n if (typeof popup.focus === 'function') {\n popup.focus();\n }\n return new Promise((resolve, reject) => {\n const bc = new BroadcastChannel(options.broadcastChannelName || 'oauth-channel');\n bc.addEventListener('message', (event) => {\n if (event.data.startsWith(options.redirectUri)) {\n bc.close();\n resolve({ redirectedUri: event.data });\n }\n else {\n bc.close();\n reject(new Error('Redirect URI does not match, expected ' + options.redirectUri + ' but got ' + event.data));\n }\n });\n setTimeout(() => {\n bc.close();\n reject(new Error('The sign-in flow timed out'));\n }, 5 * 60000);\n });\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["BackgroundColor","ToolBarType","InvisibilityMode","registerPlugin","WebPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var BackgroundColor;\n(function (BackgroundColor) {\n BackgroundColor[\"WHITE\"] = \"white\";\n BackgroundColor[\"BLACK\"] = \"black\";\n})(BackgroundColor || (BackgroundColor = {}));\nexport var ToolBarType;\n(function (ToolBarType) {\n /**\n * Shows a simple toolbar with just a close button and share button\n * @since 0.1.0\n */\n ToolBarType[\"ACTIVITY\"] = \"activity\";\n /**\n * Shows a simple toolbar with just a close button\n * @since 7.6.8\n */\n ToolBarType[\"COMPACT\"] = \"compact\";\n /**\n * Shows a full navigation toolbar with back/forward buttons\n * @since 0.1.0\n */\n ToolBarType[\"NAVIGATION\"] = \"navigation\";\n /**\n * Shows no toolbar\n * @since 0.1.0\n */\n ToolBarType[\"BLANK\"] = \"blank\";\n})(ToolBarType || (ToolBarType = {}));\nexport var InvisibilityMode;\n(function (InvisibilityMode) {\n /**\n * WebView is aware it is hidden (dimensions may be zero).\n */\n InvisibilityMode[\"AWARE\"] = \"AWARE\";\n /**\n * WebView is hidden but reports fullscreen dimensions (uses alpha=0 to remain invisible).\n */\n InvisibilityMode[\"FAKE_VISIBLE\"] = \"FAKE_VISIBLE\";\n})(InvisibilityMode || (InvisibilityMode = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst InAppBrowser = registerPlugin('InAppBrowser', {\n web: () => import('./web').then((m) => new m.InAppBrowserWeb()),\n});\nfunction arrayBufferToBase64(buffer) {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\nfunction headersToRecord(headers) {\n const result = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n}\nfunction isProxyResponse(obj) {\n return obj !== null && typeof obj === 'object' && 'status' in obj && 'headers' in obj && !(obj instanceof Response);\n}\n/**\n * Register a handler that intercepts all HTTP/HTTPS requests from the in-app browser webview.\n *\n * The callback receives a {@link ProxyRequest} for every request and must return one of:\n * - A {@link ProxyResponse} object (recommended — use with CapacitorHttp for CORS-free fetching)\n * - A fetch `Response` object\n * - `null` to let the request pass through to its original destination\n *\n * **Platform note (Android):** Requests initiated directly by HTML elements (`<img>`,\n * `<script>`, `<link>`, `<iframe>`, etc.) are intercepted via `shouldInterceptRequest`,\n * which does not expose the request body. These requests will have an empty `body` field.\n * In practice this only affects direct resource loads, which are always GET. Requests made\n * via `fetch()` or `XMLHttpRequest` go through the JS bridge and include the full body.\n *\n * @since 9.0.0\n */\nconst addProxyHandler = (callback) => {\n return InAppBrowser.addListener('proxyRequest', async (event) => {\n try {\n const result = await callback(event);\n if (result === null) {\n await InAppBrowser.handleProxyRequest({\n requestId: event.requestId,\n webviewId: event.webviewId,\n response: null,\n });\n }\n else if (isProxyResponse(result)) {\n // ProxyResponse returned directly (e.g. from CapacitorHttp)\n await InAppBrowser.handleProxyRequest({\n requestId: event.requestId,\n webviewId: event.webviewId,\n response: result,\n });\n }\n else {\n // fetch Response object\n const cloned = result.clone();\n const buffer = await cloned.arrayBuffer();\n const base64Body = arrayBufferToBase64(buffer);\n await InAppBrowser.handleProxyRequest({\n requestId: event.requestId,\n webviewId: event.webviewId,\n response: {\n body: base64Body,\n status: result.status,\n headers: headersToRecord(result.headers),\n },\n });\n }\n }\n catch (_e) {\n await InAppBrowser.handleProxyRequest({\n requestId: event.requestId,\n webviewId: event.webviewId,\n response: null,\n });\n }\n });\n};\nexport * from './definitions';\nexport { InAppBrowser, addProxyHandler };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class InAppBrowserWeb extends WebPlugin {\n clearAllCookies() {\n console.log('clearAllCookies');\n return Promise.resolve();\n }\n clearCache() {\n console.log('clearCache');\n return Promise.resolve();\n }\n async open(options) {\n console.log('open', options);\n return options;\n }\n async clearCookies(options) {\n console.log('cleanCookies', options);\n return;\n }\n async getCookies(options) {\n // Web implementation to get cookies\n return options;\n }\n async openWebView(options) {\n console.log('openWebView', options);\n return options;\n }\n async executeScript({ code }) {\n console.log('code', code);\n return code;\n }\n async close() {\n console.log('close');\n return;\n }\n async hide() {\n console.log('hide');\n return;\n }\n async show() {\n console.log('show');\n return;\n }\n async setUrl(options) {\n console.log('setUrl', options.url);\n return;\n }\n async reload() {\n console.log('reload');\n return;\n }\n async postMessage(options) {\n console.log('postMessage', options);\n return options;\n }\n async goBack() {\n console.log('goBack');\n return;\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n async handleProxyRequest() {\n // No-op on web\n return;\n }\n async updateDimensions(options) {\n console.log('updateDimensions', options);\n // Web platform doesn't support dimension control\n return;\n }\n async openSecureWindow(options) {\n const w = 600;\n const h = 550;\n const settings = [\n ['width', w],\n ['height', h],\n ['left', screen.width / 2 - w / 2],\n ['top', screen.height / 2 - h / 2],\n ]\n .map((x) => x.join('='))\n .join(',');\n const popup = window.open(options.authEndpoint, 'Authorization', settings);\n if (typeof popup.focus === 'function') {\n popup.focus();\n }\n return new Promise((resolve, reject) => {\n const bc = new BroadcastChannel(options.broadcastChannelName || 'oauth-channel');\n bc.addEventListener('message', (event) => {\n if (event.data.startsWith(options.redirectUri)) {\n bc.close();\n resolve({ redirectedUri: event.data });\n }\n else {\n bc.close();\n reject(new Error('Redirect URI does not match, expected ' + options.redirectUri + ' but got ' + event.data));\n }\n });\n setTimeout(() => {\n bc.close();\n reject(new Error('The sign-in flow timed out'));\n }, 5 * 60000);\n });\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["BackgroundColor","ToolBarType","InvisibilityMode","registerPlugin","WebPlugin"],"mappings":"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"}
package/dist/plugin.js CHANGED
@@ -44,6 +44,84 @@ var capacitorInAppBrowser = (function (exports, core) {
44
44
  const InAppBrowser = core.registerPlugin('InAppBrowser', {
45
45
  web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.InAppBrowserWeb()),
46
46
  });
47
+ function arrayBufferToBase64(buffer) {
48
+ const bytes = new Uint8Array(buffer);
49
+ let binary = '';
50
+ for (let i = 0; i < bytes.byteLength; i++) {
51
+ binary += String.fromCharCode(bytes[i]);
52
+ }
53
+ return btoa(binary);
54
+ }
55
+ function headersToRecord(headers) {
56
+ const result = {};
57
+ headers.forEach((value, key) => {
58
+ result[key] = value;
59
+ });
60
+ return result;
61
+ }
62
+ function isProxyResponse(obj) {
63
+ return obj !== null && typeof obj === 'object' && 'status' in obj && 'headers' in obj && !(obj instanceof Response);
64
+ }
65
+ /**
66
+ * Register a handler that intercepts all HTTP/HTTPS requests from the in-app browser webview.
67
+ *
68
+ * The callback receives a {@link ProxyRequest} for every request and must return one of:
69
+ * - A {@link ProxyResponse} object (recommended — use with CapacitorHttp for CORS-free fetching)
70
+ * - A fetch `Response` object
71
+ * - `null` to let the request pass through to its original destination
72
+ *
73
+ * **Platform note (Android):** Requests initiated directly by HTML elements (`<img>`,
74
+ * `<script>`, `<link>`, `<iframe>`, etc.) are intercepted via `shouldInterceptRequest`,
75
+ * which does not expose the request body. These requests will have an empty `body` field.
76
+ * In practice this only affects direct resource loads, which are always GET. Requests made
77
+ * via `fetch()` or `XMLHttpRequest` go through the JS bridge and include the full body.
78
+ *
79
+ * @since 9.0.0
80
+ */
81
+ const addProxyHandler = (callback) => {
82
+ return InAppBrowser.addListener('proxyRequest', async (event) => {
83
+ try {
84
+ const result = await callback(event);
85
+ if (result === null) {
86
+ await InAppBrowser.handleProxyRequest({
87
+ requestId: event.requestId,
88
+ webviewId: event.webviewId,
89
+ response: null,
90
+ });
91
+ }
92
+ else if (isProxyResponse(result)) {
93
+ // ProxyResponse returned directly (e.g. from CapacitorHttp)
94
+ await InAppBrowser.handleProxyRequest({
95
+ requestId: event.requestId,
96
+ webviewId: event.webviewId,
97
+ response: result,
98
+ });
99
+ }
100
+ else {
101
+ // fetch Response object
102
+ const cloned = result.clone();
103
+ const buffer = await cloned.arrayBuffer();
104
+ const base64Body = arrayBufferToBase64(buffer);
105
+ await InAppBrowser.handleProxyRequest({
106
+ requestId: event.requestId,
107
+ webviewId: event.webviewId,
108
+ response: {
109
+ body: base64Body,
110
+ status: result.status,
111
+ headers: headersToRecord(result.headers),
112
+ },
113
+ });
114
+ }
115
+ }
116
+ catch (_e) {
117
+ await InAppBrowser.handleProxyRequest({
118
+ requestId: event.requestId,
119
+ webviewId: event.webviewId,
120
+ response: null,
121
+ });
122
+ }
123
+ });
124
+ };
47
125
 
48
126
  class InAppBrowserWeb extends core.WebPlugin {
49
127
  clearAllCookies() {
@@ -105,6 +183,10 @@ var capacitorInAppBrowser = (function (exports, core) {
105
183
  async getPluginVersion() {
106
184
  return { version: 'web' };
107
185
  }
186
+ async handleProxyRequest() {
187
+ // No-op on web
188
+ return;
189
+ }
108
190
  async updateDimensions(options) {
109
191
  console.log('updateDimensions', options);
110
192
  // Web platform doesn't support dimension control
@@ -151,6 +233,7 @@ var capacitorInAppBrowser = (function (exports, core) {
151
233
  });
152
234
 
153
235
  exports.InAppBrowser = InAppBrowser;
236
+ exports.addProxyHandler = addProxyHandler;
154
237
 
155
238
  return exports;
156
239
 
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var BackgroundColor;\n(function (BackgroundColor) {\n BackgroundColor[\"WHITE\"] = \"white\";\n BackgroundColor[\"BLACK\"] = \"black\";\n})(BackgroundColor || (BackgroundColor = {}));\nexport var ToolBarType;\n(function (ToolBarType) {\n /**\n * Shows a simple toolbar with just a close button and share button\n * @since 0.1.0\n */\n ToolBarType[\"ACTIVITY\"] = \"activity\";\n /**\n * Shows a simple toolbar with just a close button\n * @since 7.6.8\n */\n ToolBarType[\"COMPACT\"] = \"compact\";\n /**\n * Shows a full navigation toolbar with back/forward buttons\n * @since 0.1.0\n */\n ToolBarType[\"NAVIGATION\"] = \"navigation\";\n /**\n * Shows no toolbar\n * @since 0.1.0\n */\n ToolBarType[\"BLANK\"] = \"blank\";\n})(ToolBarType || (ToolBarType = {}));\nexport var InvisibilityMode;\n(function (InvisibilityMode) {\n /**\n * WebView is aware it is hidden (dimensions may be zero).\n */\n InvisibilityMode[\"AWARE\"] = \"AWARE\";\n /**\n * WebView is hidden but reports fullscreen dimensions (uses alpha=0 to remain invisible).\n */\n InvisibilityMode[\"FAKE_VISIBLE\"] = \"FAKE_VISIBLE\";\n})(InvisibilityMode || (InvisibilityMode = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst InAppBrowser = registerPlugin('InAppBrowser', {\n web: () => import('./web').then((m) => new m.InAppBrowserWeb()),\n});\nexport * from './definitions';\nexport { InAppBrowser };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class InAppBrowserWeb extends WebPlugin {\n clearAllCookies() {\n console.log('clearAllCookies');\n return Promise.resolve();\n }\n clearCache() {\n console.log('clearCache');\n return Promise.resolve();\n }\n async open(options) {\n console.log('open', options);\n return options;\n }\n async clearCookies(options) {\n console.log('cleanCookies', options);\n return;\n }\n async getCookies(options) {\n // Web implementation to get cookies\n return options;\n }\n async openWebView(options) {\n console.log('openWebView', options);\n return options;\n }\n async executeScript({ code }) {\n console.log('code', code);\n return code;\n }\n async close() {\n console.log('close');\n return;\n }\n async hide() {\n console.log('hide');\n return;\n }\n async show() {\n console.log('show');\n return;\n }\n async setUrl(options) {\n console.log('setUrl', options.url);\n return;\n }\n async reload() {\n console.log('reload');\n return;\n }\n async postMessage(options) {\n console.log('postMessage', options);\n return options;\n }\n async goBack() {\n console.log('goBack');\n return;\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n async updateDimensions(options) {\n console.log('updateDimensions', options);\n // Web platform doesn't support dimension control\n return;\n }\n async openSecureWindow(options) {\n const w = 600;\n const h = 550;\n const settings = [\n ['width', w],\n ['height', h],\n ['left', screen.width / 2 - w / 2],\n ['top', screen.height / 2 - h / 2],\n ]\n .map((x) => x.join('='))\n .join(',');\n const popup = window.open(options.authEndpoint, 'Authorization', settings);\n if (typeof popup.focus === 'function') {\n popup.focus();\n }\n return new Promise((resolve, reject) => {\n const bc = new BroadcastChannel(options.broadcastChannelName || 'oauth-channel');\n bc.addEventListener('message', (event) => {\n if (event.data.startsWith(options.redirectUri)) {\n bc.close();\n resolve({ redirectedUri: event.data });\n }\n else {\n bc.close();\n reject(new Error('Redirect URI does not match, expected ' + options.redirectUri + ' but got ' + event.data));\n }\n });\n setTimeout(() => {\n bc.close();\n reject(new Error('The sign-in flow timed out'));\n }, 5 * 60000);\n });\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["BackgroundColor","ToolBarType","InvisibilityMode","registerPlugin","WebPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var BackgroundColor;\n(function (BackgroundColor) {\n BackgroundColor[\"WHITE\"] = \"white\";\n BackgroundColor[\"BLACK\"] = \"black\";\n})(BackgroundColor || (BackgroundColor = {}));\nexport var ToolBarType;\n(function (ToolBarType) {\n /**\n * Shows a simple toolbar with just a close button and share button\n * @since 0.1.0\n */\n ToolBarType[\"ACTIVITY\"] = \"activity\";\n /**\n * Shows a simple toolbar with just a close button\n * @since 7.6.8\n */\n ToolBarType[\"COMPACT\"] = \"compact\";\n /**\n * Shows a full navigation toolbar with back/forward buttons\n * @since 0.1.0\n */\n ToolBarType[\"NAVIGATION\"] = \"navigation\";\n /**\n * Shows no toolbar\n * @since 0.1.0\n */\n ToolBarType[\"BLANK\"] = \"blank\";\n})(ToolBarType || (ToolBarType = {}));\nexport var InvisibilityMode;\n(function (InvisibilityMode) {\n /**\n * WebView is aware it is hidden (dimensions may be zero).\n */\n InvisibilityMode[\"AWARE\"] = \"AWARE\";\n /**\n * WebView is hidden but reports fullscreen dimensions (uses alpha=0 to remain invisible).\n */\n InvisibilityMode[\"FAKE_VISIBLE\"] = \"FAKE_VISIBLE\";\n})(InvisibilityMode || (InvisibilityMode = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst InAppBrowser = registerPlugin('InAppBrowser', {\n web: () => import('./web').then((m) => new m.InAppBrowserWeb()),\n});\nfunction arrayBufferToBase64(buffer) {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\nfunction headersToRecord(headers) {\n const result = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n}\nfunction isProxyResponse(obj) {\n return obj !== null && typeof obj === 'object' && 'status' in obj && 'headers' in obj && !(obj instanceof Response);\n}\n/**\n * Register a handler that intercepts all HTTP/HTTPS requests from the in-app browser webview.\n *\n * The callback receives a {@link ProxyRequest} for every request and must return one of:\n * - A {@link ProxyResponse} object (recommended — use with CapacitorHttp for CORS-free fetching)\n * - A fetch `Response` object\n * - `null` to let the request pass through to its original destination\n *\n * **Platform note (Android):** Requests initiated directly by HTML elements (`<img>`,\n * `<script>`, `<link>`, `<iframe>`, etc.) are intercepted via `shouldInterceptRequest`,\n * which does not expose the request body. These requests will have an empty `body` field.\n * In practice this only affects direct resource loads, which are always GET. Requests made\n * via `fetch()` or `XMLHttpRequest` go through the JS bridge and include the full body.\n *\n * @since 9.0.0\n */\nconst addProxyHandler = (callback) => {\n return InAppBrowser.addListener('proxyRequest', async (event) => {\n try {\n const result = await callback(event);\n if (result === null) {\n await InAppBrowser.handleProxyRequest({\n requestId: event.requestId,\n webviewId: event.webviewId,\n response: null,\n });\n }\n else if (isProxyResponse(result)) {\n // ProxyResponse returned directly (e.g. from CapacitorHttp)\n await InAppBrowser.handleProxyRequest({\n requestId: event.requestId,\n webviewId: event.webviewId,\n response: result,\n });\n }\n else {\n // fetch Response object\n const cloned = result.clone();\n const buffer = await cloned.arrayBuffer();\n const base64Body = arrayBufferToBase64(buffer);\n await InAppBrowser.handleProxyRequest({\n requestId: event.requestId,\n webviewId: event.webviewId,\n response: {\n body: base64Body,\n status: result.status,\n headers: headersToRecord(result.headers),\n },\n });\n }\n }\n catch (_e) {\n await InAppBrowser.handleProxyRequest({\n requestId: event.requestId,\n webviewId: event.webviewId,\n response: null,\n });\n }\n });\n};\nexport * from './definitions';\nexport { InAppBrowser, addProxyHandler };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class InAppBrowserWeb extends WebPlugin {\n clearAllCookies() {\n console.log('clearAllCookies');\n return Promise.resolve();\n }\n clearCache() {\n console.log('clearCache');\n return Promise.resolve();\n }\n async open(options) {\n console.log('open', options);\n return options;\n }\n async clearCookies(options) {\n console.log('cleanCookies', options);\n return;\n }\n async getCookies(options) {\n // Web implementation to get cookies\n return options;\n }\n async openWebView(options) {\n console.log('openWebView', options);\n return options;\n }\n async executeScript({ code }) {\n console.log('code', code);\n return code;\n }\n async close() {\n console.log('close');\n return;\n }\n async hide() {\n console.log('hide');\n return;\n }\n async show() {\n console.log('show');\n return;\n }\n async setUrl(options) {\n console.log('setUrl', options.url);\n return;\n }\n async reload() {\n console.log('reload');\n return;\n }\n async postMessage(options) {\n console.log('postMessage', options);\n return options;\n }\n async goBack() {\n console.log('goBack');\n return;\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n async handleProxyRequest() {\n // No-op on web\n return;\n }\n async updateDimensions(options) {\n console.log('updateDimensions', options);\n // Web platform doesn't support dimension control\n return;\n }\n async openSecureWindow(options) {\n const w = 600;\n const h = 550;\n const settings = [\n ['width', w],\n ['height', h],\n ['left', screen.width / 2 - w / 2],\n ['top', screen.height / 2 - h / 2],\n ]\n .map((x) => x.join('='))\n .join(',');\n const popup = window.open(options.authEndpoint, 'Authorization', settings);\n if (typeof popup.focus === 'function') {\n popup.focus();\n }\n return new Promise((resolve, reject) => {\n const bc = new BroadcastChannel(options.broadcastChannelName || 'oauth-channel');\n bc.addEventListener('message', (event) => {\n if (event.data.startsWith(options.redirectUri)) {\n bc.close();\n resolve({ redirectedUri: event.data });\n }\n else {\n bc.close();\n reject(new Error('Redirect URI does not match, expected ' + options.redirectUri + ' but got ' + event.data));\n }\n });\n setTimeout(() => {\n bc.close();\n reject(new Error('The sign-in flow timed out'));\n }, 5 * 60000);\n });\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["BackgroundColor","ToolBarType","InvisibilityMode","registerPlugin","WebPlugin"],"mappings":"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"}
@@ -29,7 +29,7 @@ public class InAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
29
29
  case aware = "AWARE"
30
30
  case fakeVisible = "FAKE_VISIBLE"
31
31
  }
32
- private let pluginVersion: String = "8.2.0"
32
+ private let pluginVersion: String = "8.3.0-alpha.1"
33
33
  public let identifier = "InAppBrowserPlugin"
34
34
  public let jsName = "InAppBrowser"
35
35
  public let pluginMethods: [CAPPluginMethod] = [
@@ -50,6 +50,7 @@ public class InAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
50
50
  CAPPluginMethod(name: "updateDimensions", returnType: CAPPluginReturnPromise),
51
51
  CAPPluginMethod(name: "getPluginVersion", returnType: CAPPluginReturnPromise),
52
52
  CAPPluginMethod(name: "openSecureWindow", returnType: CAPPluginReturnPromise),
53
+ CAPPluginMethod(name: "handleProxyRequest", returnType: CAPPluginReturnPromise),
53
54
  ]
54
55
  var navigationWebViewController: UINavigationController?
55
56
  private var navigationControllers: [String: UINavigationController] = [:]
@@ -61,6 +62,7 @@ public class InAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
61
62
  var invisibilityMode: InvisibilityMode = .aware
62
63
  var webViewController: WKWebViewController?
63
64
  private var webViewControllers: [String: WKWebViewController] = [:]
65
+ private var proxySchemeHandlers: [String: ProxySchemeHandler] = [:]
64
66
  private var webViewStack: [String] = []
65
67
  private var activeWebViewId: String?
66
68
  private weak var presentationContainerView: UIView?
@@ -95,6 +97,8 @@ public class InAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
95
97
  }
96
98
 
97
99
  private func unregisterWebView(id: String) {
100
+ proxySchemeHandlers[id]?.cancelAllPendingTasks()
101
+ proxySchemeHandlers[id] = nil
98
102
  webViewControllers[id] = nil
99
103
  navigationControllers[id] = nil
100
104
  webViewStack.removeAll { $0 == id }
@@ -593,6 +597,9 @@ public class InAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
593
597
  // Read disableOverscroll option (iOS only - controls WebView bounce effect)
594
598
  let disableOverscroll = call.getBool("disableOverscroll", false)
595
599
 
600
+ // Read proxy option
601
+ let proxyRequests = call.getBool("proxyRequests") ?? false
602
+
596
603
  // Validate dimension parameters
597
604
  if width != nil && height == nil {
598
605
  call.reject("Height must be specified when width is provided")
@@ -605,6 +612,13 @@ public class InAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
605
612
  return
606
613
  }
607
614
 
615
+ // Create proxy handler before init so it's available during initWebview()
616
+ var proxyHandler: ProxySchemeHandler? = nil
617
+ if proxyRequests {
618
+ proxyHandler = ProxySchemeHandler(plugin: self, webviewId: webViewId)
619
+ self.proxySchemeHandlers[webViewId] = proxyHandler!
620
+ }
621
+
608
622
  self.webViewController = WKWebViewController.init(
609
623
  url: url,
610
624
  headers: headers,
@@ -616,6 +630,8 @@ public class InAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
616
630
  enabledSafeTopMargin: enabledSafeTopMargin,
617
631
  blockedHosts: blockedHosts,
618
632
  authorizedAppLinks: authorizedAppLinks,
633
+ proxyRequests: proxyRequests,
634
+ proxySchemeHandler: proxyHandler
619
635
  )
620
636
 
621
637
  guard let webViewController = self.webViewController else {
@@ -1231,6 +1247,53 @@ public class InAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1231
1247
  }
1232
1248
  }
1233
1249
 
1250
+ @objc func handleProxyRequest(_ call: CAPPluginCall) {
1251
+ guard let requestId = call.getString("requestId") else {
1252
+ call.reject("requestId is required")
1253
+ return
1254
+ }
1255
+
1256
+ let webviewId = call.getString("webviewId")
1257
+ let responseObj = call.getObject("response")
1258
+
1259
+ // Find the handler
1260
+ var handler: ProxySchemeHandler?
1261
+ if let webviewId = webviewId {
1262
+ handler = proxySchemeHandlers[webviewId]
1263
+ } else if proxySchemeHandlers.count == 1 {
1264
+ handler = proxySchemeHandlers.values.first
1265
+ } else if proxySchemeHandlers.count > 1 {
1266
+ print("[InAppBrowser] handleProxyRequest: webviewId is nil but \(proxySchemeHandlers.count) webviews are active — cannot determine target, aborting")
1267
+ call.reject("webviewId is required when multiple webviews are open")
1268
+ return
1269
+ }
1270
+
1271
+ guard let proxyHandler = handler else {
1272
+ call.reject("No proxy handler found")
1273
+ return
1274
+ }
1275
+
1276
+ var responseDict: [String: Any]? = nil
1277
+ if let responseObj = responseObj {
1278
+ var dict: [String: Any] = [:]
1279
+ dict["status"] = responseObj["status"]
1280
+ dict["body"] = responseObj["body"]
1281
+ if let headers = responseObj["headers"] as? JSObject {
1282
+ var headersDict: [String: String] = [:]
1283
+ for (key, value) in headers {
1284
+ if let strValue = value as? String {
1285
+ headersDict[key] = strValue
1286
+ }
1287
+ }
1288
+ dict["headers"] = headersDict
1289
+ }
1290
+ responseDict = dict
1291
+ }
1292
+
1293
+ proxyHandler.handleResponse(requestId: requestId, responseData: responseDict)
1294
+ call.resolve()
1295
+ }
1296
+
1234
1297
  @objc func close(_ call: CAPPluginCall) {
1235
1298
  let isAnimated = call.getBool("isAnimated", true)
1236
1299
 
@@ -0,0 +1,233 @@
1
+ import Foundation
2
+ import WebKit
3
+ import Capacitor
4
+
5
+ public class ProxySchemeHandler: NSObject, WKURLSchemeHandler {
6
+ weak var plugin: InAppBrowserPlugin?
7
+ private var pendingTasks: [String: WKURLSchemeTask] = [:]
8
+ private var pendingBodies: [String: Data] = [:]
9
+ private var activeTasks: [Int: (requestId: String, schemeTask: WKURLSchemeTask, dataTask: URLSessionDataTask)] = [:]
10
+ private var stoppedRequests: Set<String> = []
11
+ private let taskLock = NSLock()
12
+ private let webviewId: String
13
+ private let proxyTimeoutSeconds: TimeInterval = 10
14
+
15
+ private static var session: URLSession = {
16
+ return URLSession(configuration: .default)
17
+ }()
18
+
19
+ init(plugin: InAppBrowserPlugin, webviewId: String) {
20
+ self.plugin = plugin
21
+ self.webviewId = webviewId
22
+ super.init()
23
+ }
24
+
25
+ public func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
26
+ let request = urlSchemeTask.request
27
+ guard let url = request.url else {
28
+ urlSchemeTask.didFailWithError(NSError(
29
+ domain: "ProxySchemeHandler",
30
+ code: -1,
31
+ userInfo: [NSLocalizedDescriptionKey: "No URL in request"]
32
+ ))
33
+ return
34
+ }
35
+
36
+ let requestId = UUID().uuidString
37
+
38
+ taskLock.lock()
39
+ pendingTasks[requestId] = urlSchemeTask
40
+ taskLock.unlock()
41
+
42
+ // Buffer body from stream if needed (stream can only be read once)
43
+ var base64Body: String? = nil
44
+ if let bodyData = request.httpBody {
45
+ base64Body = bodyData.base64EncodedString()
46
+ } else if let bodyStream = request.httpBodyStream {
47
+ let data = Data(reading: bodyStream)
48
+ if !data.isEmpty {
49
+ base64Body = data.base64EncodedString()
50
+ taskLock.lock()
51
+ pendingBodies[requestId] = data
52
+ taskLock.unlock()
53
+ }
54
+ }
55
+
56
+ // Build headers dict
57
+ var headers: [String: String] = [:]
58
+ if let allHeaders = request.allHTTPHeaderFields {
59
+ headers = allHeaders
60
+ }
61
+
62
+ let eventData: [String: Any] = [
63
+ "requestId": requestId,
64
+ "url": url.absoluteString,
65
+ "method": request.httpMethod ?? "GET",
66
+ "headers": headers,
67
+ "body": base64Body as Any,
68
+ "webviewId": webviewId,
69
+ ]
70
+
71
+ plugin?.notifyListeners("proxyRequest", data: eventData)
72
+
73
+ // Timeout: if JS never responds, fail the request
74
+ DispatchQueue.global().asyncAfter(deadline: .now() + proxyTimeoutSeconds) { [weak self] in
75
+ guard let self = self else { return }
76
+ self.taskLock.lock()
77
+ guard let task = self.pendingTasks.removeValue(forKey: requestId) else {
78
+ self.taskLock.unlock()
79
+ return
80
+ }
81
+ self.pendingBodies.removeValue(forKey: requestId)
82
+ self.taskLock.unlock()
83
+
84
+ task.didFailWithError(NSError(
85
+ domain: "ProxySchemeHandler",
86
+ code: NSURLErrorTimedOut,
87
+ userInfo: [NSLocalizedDescriptionKey: "Proxy handler did not respond within \(Int(self.proxyTimeoutSeconds)) seconds"]
88
+ ))
89
+ }
90
+ }
91
+
92
+ public func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
93
+ taskLock.lock()
94
+ // Check pending (waiting for JS)
95
+ if let key = pendingTasks.first(where: { $0.value === urlSchemeTask })?.key {
96
+ pendingTasks.removeValue(forKey: key)
97
+ pendingBodies.removeValue(forKey: key)
98
+ stoppedRequests.insert(key)
99
+ }
100
+ // Check active network tasks (pass-through) — cancel the URLSessionDataTask
101
+ var networkTaskToCancel: URLSessionDataTask?
102
+ if let entry = activeTasks.first(where: { $0.value.schemeTask === urlSchemeTask }) {
103
+ networkTaskToCancel = entry.value.dataTask
104
+ activeTasks.removeValue(forKey: entry.key)
105
+ stoppedRequests.insert(entry.value.requestId)
106
+ }
107
+ taskLock.unlock()
108
+ networkTaskToCancel?.cancel()
109
+ }
110
+
111
+ /// Called from handleProxyRequest plugin method with the JS response
112
+ func handleResponse(requestId: String, responseData: [String: Any]?) {
113
+ taskLock.lock()
114
+ let isStopped = stoppedRequests.remove(requestId) != nil
115
+ guard let urlSchemeTask = pendingTasks.removeValue(forKey: requestId) else {
116
+ taskLock.unlock()
117
+ return
118
+ }
119
+ let bufferedBody = pendingBodies.removeValue(forKey: requestId)
120
+ taskLock.unlock()
121
+
122
+ if isStopped { return }
123
+
124
+ if let responseData = responseData {
125
+ // JS provided a response — return it directly
126
+ let statusCode = responseData["status"] as? Int ?? 200
127
+ let headersDict = responseData["headers"] as? [String: String] ?? [:]
128
+ let base64Body = responseData["body"] as? String ?? ""
129
+ let bodyData = Data(base64Encoded: base64Body) ?? Data()
130
+
131
+ guard let url = urlSchemeTask.request.url,
132
+ let httpResponse = HTTPURLResponse(
133
+ url: url, statusCode: statusCode,
134
+ httpVersion: "HTTP/1.1", headerFields: headersDict
135
+ ) else {
136
+ urlSchemeTask.didFailWithError(NSError(
137
+ domain: "ProxySchemeHandler", code: -2,
138
+ userInfo: [NSLocalizedDescriptionKey: "Failed to create response"]
139
+ ))
140
+ return
141
+ }
142
+
143
+ urlSchemeTask.didReceive(httpResponse)
144
+ urlSchemeTask.didReceive(bodyData)
145
+ urlSchemeTask.didFinish()
146
+ } else {
147
+ // Null response = pass-through via URLSession
148
+ executePassThrough(requestId: requestId, urlSchemeTask: urlSchemeTask, bufferedBody: bufferedBody)
149
+ }
150
+ }
151
+
152
+ private func executePassThrough(requestId: String, urlSchemeTask: WKURLSchemeTask, bufferedBody: Data?) {
153
+ var request = urlSchemeTask.request
154
+ if request.httpBody == nil, let body = bufferedBody {
155
+ request.httpBody = body
156
+ }
157
+
158
+ let task = Self.session.dataTask(with: request) { [weak self, weak urlSchemeTask] data, response, error in
159
+ guard let urlSchemeTask = urlSchemeTask else { return }
160
+ guard let self = self else { return }
161
+
162
+ // Clean up active entry and check not stopped
163
+ self.taskLock.lock()
164
+ if let entry = self.activeTasks.first(where: { $0.value.requestId == requestId }) {
165
+ self.activeTasks.removeValue(forKey: entry.key)
166
+ }
167
+ let wasStopped = self.stoppedRequests.remove(requestId) != nil
168
+ self.taskLock.unlock()
169
+ if wasStopped { return }
170
+
171
+ if let error = error {
172
+ if (error as NSError).code != NSURLErrorCancelled {
173
+ urlSchemeTask.didFailWithError(error)
174
+ }
175
+ } else {
176
+ if let response = response {
177
+ urlSchemeTask.didReceive(response)
178
+ }
179
+ if let data = data {
180
+ urlSchemeTask.didReceive(data)
181
+ }
182
+ urlSchemeTask.didFinish()
183
+ }
184
+ }
185
+
186
+ taskLock.lock()
187
+ activeTasks[task.taskIdentifier] = (requestId: requestId, schemeTask: urlSchemeTask, dataTask: task)
188
+ taskLock.unlock()
189
+
190
+ task.resume()
191
+ }
192
+
193
+ func cancelAllPendingTasks() {
194
+ taskLock.lock()
195
+ let pending = pendingTasks
196
+ let active = activeTasks
197
+ pendingTasks.removeAll()
198
+ pendingBodies.removeAll()
199
+ activeTasks.removeAll()
200
+ stoppedRequests.removeAll()
201
+ taskLock.unlock()
202
+
203
+ for (_, entry) in active {
204
+ entry.dataTask.cancel()
205
+ }
206
+
207
+ for (_, task) in pending {
208
+ task.didFailWithError(NSError(
209
+ domain: "ProxySchemeHandler",
210
+ code: NSURLErrorCancelled,
211
+ userInfo: [NSLocalizedDescriptionKey: "WebView closed"]
212
+ ))
213
+ }
214
+ }
215
+ }
216
+
217
+ extension Data {
218
+ init(reading input: InputStream) {
219
+ self.init()
220
+ input.open()
221
+ let bufferSize = 1024
222
+ let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
223
+ while input.hasBytesAvailable {
224
+ let read = input.read(buffer, maxLength: bufferSize)
225
+ if read < 0 {
226
+ break
227
+ }
228
+ self.append(buffer, count: read)
229
+ }
230
+ buffer.deallocate()
231
+ input.close()
232
+ }
233
+ }