@capgo/capacitor-inappbrowser 8.14.3 → 8.15.0

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.
@@ -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 = {}));\nexport var CloseAction;\n(function (CloseAction) {\n /**\n * The toolbar close button closes and destroys the webview.\n */\n CloseAction[\"CLOSE\"] = \"close\";\n /**\n * The toolbar close button hides the webview so it can be shown again.\n */\n CloseAction[\"HIDE\"] = \"hide\";\n})(CloseAction || (CloseAction = {}));\n//# sourceMappingURL=definitions.js.map","import { Capacitor, registerPlugin } from '@capacitor/core';\nconst CAPGO_PLUGIN_NAME = 'CapgoInAppBrowser';\nconst PREVIOUS_PLUGIN_NAME = 'InAppBrowser';\nfunction resolvePluginName() {\n if (!Capacitor.isNativePlatform()) {\n return CAPGO_PLUGIN_NAME;\n }\n if (Capacitor.isPluginAvailable(CAPGO_PLUGIN_NAME)) {\n return CAPGO_PLUGIN_NAME;\n }\n if (Capacitor.isPluginAvailable(PREVIOUS_PLUGIN_NAME)) {\n return PREVIOUS_PLUGIN_NAME;\n }\n console.warn(`[InAppBrowser] Neither '${CAPGO_PLUGIN_NAME}' nor '${PREVIOUS_PLUGIN_NAME}' native plugin detected. ` +\n 'Ensure @capgo/capacitor-inappbrowser native code is installed.');\n return CAPGO_PLUGIN_NAME;\n}\nconst inAppBrowserImplementations = {\n web: () => import('./web').then((m) => new m.InAppBrowserWeb()),\n};\nconst InAppBrowser = registerPlugin(resolvePluginName(), inAppBrowserImplementations);\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 errorMessage(error) {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === 'string') {\n return error;\n }\n if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n return error.message;\n }\n return String(error);\n}\nfunction isStaleProxyResponseError(error) {\n const message = errorMessage(error);\n return message.includes('No proxy handler found') || message.includes('Target WebView not found for proxy request');\n}\nfunction isProxyResponse(value) {\n return (value !== null &&\n typeof value === 'object' &&\n 'status' in value &&\n 'headers' in value &&\n !(value instanceof Response));\n}\nfunction isProxyRequestOverride(value) {\n return value !== null && typeof value === 'object' && 'url' in value && !(value instanceof Response);\n}\nfunction isProxyDecision(value) {\n return (value !== null && typeof value === 'object' && ('request' in value || 'response' in value || 'cancel' in value));\n}\nasync function sendProxyDecision(requestId, webviewId, decision, phase) {\n try {\n await InAppBrowser.handleProxyRequest({\n requestId,\n webviewId,\n decision,\n phase,\n });\n }\n catch (error) {\n if (isStaleProxyResponseError(error)) {\n return;\n }\n throw error;\n }\n}\nconst addProxyHandler = (callback) => {\n return InAppBrowser.addListener('proxyRequest', async (event) => {\n let decision = null;\n try {\n const result = await callback(event);\n if (result === null) {\n decision = null;\n }\n else if (isProxyDecision(result)) {\n decision = result;\n }\n else if (isProxyRequestOverride(result)) {\n decision = { request: result };\n }\n else if (isProxyResponse(result)) {\n decision = { response: result };\n }\n else {\n const cloned = result.clone();\n const buffer = await cloned.arrayBuffer();\n decision = {\n response: {\n body: arrayBufferToBase64(buffer),\n status: result.status,\n headers: headersToRecord(result.headers),\n },\n };\n }\n }\n catch (_error) {\n decision = null;\n }\n await sendProxyDecision(event.requestId, event.webviewId, decision, event.phase);\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 clearAllBrowsingData() {\n console.log('clearAllBrowsingData');\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(options) {\n console.log('close', options);\n return;\n }\n async hide(options) {\n console.log('hide', options);\n return;\n }\n async show(options) {\n console.log('show', options);\n return;\n }\n async sendToBack(options) {\n console.log('sendToBack not supported on web', options);\n return;\n }\n async bringToFront(options) {\n console.log('bringToFront not supported on web', options);\n return;\n }\n async dispatchInputEvent(options) {\n console.log('dispatchInputEvent not supported on web', options);\n return;\n }\n async setUrl(options) {\n console.log('setUrl', options.url);\n return;\n }\n async reload(options) {\n console.log('reload', options);\n return;\n }\n async postMessage(options) {\n console.log('postMessage', options);\n return options;\n }\n async takeScreenshot(options) {\n console.log('takeScreenshot not supported on web', options);\n throw this.unimplemented('Screenshots are not supported on web.');\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 handleProxyRequest(options) {\n console.log('handleProxyRequest not supported on web', options);\n return;\n }\n async setEnabledSafeTopMargin(options) {\n console.log('setEnabledSafeTopMargin not supported on web', options);\n return;\n }\n async setEnabledSafeBottomMargin(options) {\n console.log('setEnabledSafeBottomMargin not supported on web', options);\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 (!popup) {\n throw new Error('Failed to open secure window');\n }\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","CloseAction","Capacitor","registerPlugin","WebPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/bundled-asset-support.js","esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["/** Default Capacitor local URL settings used when no runtime config is available. */\nexport const BUNDLED_ASSET_DEFAULTS = {\n ios: { scheme: 'capacitor', host: 'localhost' },\n android: { scheme: 'https', host: 'localhost' },\n};\nconst ABSOLUTE_URL_PATTERN = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:/;\nconst RESERVED_WEB_SCHEMES = ['http', 'https'];\n/** Returns true when the input looks like an absolute URL (including protocol-relative URLs). */\nexport function isAbsoluteUrl(url) {\n return ABSOLUTE_URL_PATTERN.test(url) || url.startsWith('//');\n}\n/** Returns true when any path segment is `..`. */\nexport function containsPathTraversal(path) {\n return path.split('/').includes('..');\n}\n/**\n * Normalizes a relative bundled asset path to a leading-slash form.\n * Returns null when the path contains traversal segments.\n */\nexport function normalizeBundledPath(path) {\n const trimmed = path.trim();\n if (!trimmed || trimmed === '/') {\n return '/';\n }\n if (containsPathTraversal(trimmed)) {\n return null;\n }\n return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;\n}\n/** Parses a Capacitor local URL into scheme and host components. */\nexport function parseBundledLocalConfig(localUrl) {\n if (!localUrl) {\n return null;\n }\n try {\n const parsed = new URL(localUrl.endsWith('/') ? localUrl : `${localUrl}/`);\n if (!parsed.protocol || !parsed.hostname) {\n return null;\n }\n return {\n scheme: parsed.protocol.replace(/:$/, '').toLowerCase(),\n host: parsed.hostname.toLowerCase(),\n };\n }\n catch (_a) {\n return null;\n }\n}\n/** Returns the scheme WebView navigation should use for bundled assets on a platform. */\nexport function handlerSchemeForPlatform(platform, localConfig) {\n if (platform === 'ios' && RESERVED_WEB_SCHEMES.includes(localConfig.scheme)) {\n return BUNDLED_ASSET_DEFAULTS.ios.scheme;\n }\n if (platform === 'android') {\n if (localConfig.scheme === 'http' || localConfig.scheme === 'https') {\n return localConfig.scheme;\n }\n return BUNDLED_ASSET_DEFAULTS.android.scheme;\n }\n return localConfig.scheme;\n}\n/**\n * Returns true when the URL targets the configured Capacitor local host/scheme\n * (including the platform handler scheme rewrite).\n */\nexport function isBundledLocalUrl(url, platform, localConfig) {\n if (!isAbsoluteUrl(url)) {\n return false;\n }\n try {\n const parsed = new URL(url);\n const scheme = parsed.protocol.replace(/:$/, '').toLowerCase();\n const host = parsed.hostname.toLowerCase();\n const config = localConfig !== null && localConfig !== void 0 ? localConfig : BUNDLED_ASSET_DEFAULTS[platform];\n if (host !== config.host) {\n return false;\n }\n if (parsed.port !== '') {\n return false;\n }\n if (scheme === config.scheme || scheme === handlerSchemeForPlatform(platform, config)) {\n return true;\n }\n return RESERVED_WEB_SCHEMES.includes(scheme) && RESERVED_WEB_SCHEMES.includes(config.scheme);\n }\n catch (_a) {\n return false;\n }\n}\n/** Returns true when the input is a non-empty relative bundled asset path. */\nexport function isRelativeBundledPath(url) {\n const trimmed = url.trim();\n if (!trimmed) {\n return false;\n }\n return !isAbsoluteUrl(trimmed);\n}\nfunction rewriteBundledLocalUrl(url, localConfig, navigationScheme) {\n try {\n const parsed = new URL(url);\n const host = parsed.hostname.toLowerCase();\n const scheme = parsed.protocol.replace(/:$/, '').toLowerCase();\n if (host !== localConfig.host || scheme === navigationScheme) {\n return null;\n }\n const pathname = parsed.pathname || '/';\n const search = parsed.search;\n const hash = parsed.hash;\n const userinfo = parsed.username.length > 0 ? `${parsed.username}${parsed.password.length > 0 ? `:${parsed.password}` : ''}@` : '';\n return `${navigationScheme}://${userinfo}${host}${pathname}${search}${hash}`;\n }\n catch (_a) {\n return null;\n }\n}\n/**\n * Resolves a bundled asset URL for the given platform.\n * Relative paths become platform-local URLs; bundled local URLs may be rewritten to the handler scheme.\n */\nexport function resolveBundledAssetUrl(url, platform, localConfig) {\n const trimmed = url.trim();\n const config = localConfig !== null && localConfig !== void 0 ? localConfig : BUNDLED_ASSET_DEFAULTS[platform];\n const navigationScheme = handlerSchemeForPlatform(platform, config);\n if (isRelativeBundledPath(trimmed)) {\n const path = normalizeBundledPath(trimmed);\n if (path === null) {\n return null;\n }\n return {\n url: `${navigationScheme}://${config.host}${path}`,\n };\n }\n if (isBundledLocalUrl(trimmed, platform, config)) {\n const rewritten = rewriteBundledLocalUrl(trimmed, config, navigationScheme);\n return {\n url: rewritten !== null && rewritten !== void 0 ? rewritten : trimmed,\n };\n }\n return {\n url: trimmed,\n };\n}\n/**\n * Resolves relative bundled paths for legacy native plugins that do not perform native resolution.\n * Throws when the path is invalid.\n */\nexport function resolveLegacyNativeWebViewUrl(url, platform, localConfig) {\n if (!isRelativeBundledPath(url)) {\n return url;\n }\n const resolution = resolveBundledAssetUrl(url, platform, localConfig);\n if (resolution === null) {\n throw new Error('Invalid bundled asset path');\n }\n return resolution.url;\n}\n//# sourceMappingURL=bundled-asset-support.js.map","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 = {}));\nexport var CloseAction;\n(function (CloseAction) {\n /**\n * The toolbar close button closes and destroys the webview.\n */\n CloseAction[\"CLOSE\"] = \"close\";\n /**\n * The toolbar close button hides the webview so it can be shown again.\n */\n CloseAction[\"HIDE\"] = \"hide\";\n})(CloseAction || (CloseAction = {}));\n//# sourceMappingURL=definitions.js.map","import { Capacitor, registerPlugin } from '@capacitor/core';\nimport { containsPathTraversal, isRelativeBundledPath, parseBundledLocalConfig, resolveLegacyNativeWebViewUrl, } from './bundled-asset-support';\nconst CAPGO_PLUGIN_NAME = 'CapgoInAppBrowser';\nconst PREVIOUS_PLUGIN_NAME = 'InAppBrowser';\nfunction resolvePluginName() {\n if (!Capacitor.isNativePlatform()) {\n return CAPGO_PLUGIN_NAME;\n }\n if (Capacitor.isPluginAvailable(CAPGO_PLUGIN_NAME)) {\n return CAPGO_PLUGIN_NAME;\n }\n if (Capacitor.isPluginAvailable(PREVIOUS_PLUGIN_NAME)) {\n return PREVIOUS_PLUGIN_NAME;\n }\n console.warn(`[InAppBrowser] Neither '${CAPGO_PLUGIN_NAME}' nor '${PREVIOUS_PLUGIN_NAME}' native plugin detected. ` +\n 'Ensure @capgo/capacitor-inappbrowser native code is installed.');\n return CAPGO_PLUGIN_NAME;\n}\nconst inAppBrowserImplementations = {\n web: () => import('./web').then((m) => new m.InAppBrowserWeb()),\n};\nfunction assertValidBundledAssetPath(url) {\n if (isRelativeBundledPath(url) && containsPathTraversal(url)) {\n throw new Error('Invalid bundled asset path');\n }\n}\nconst activePluginName = resolvePluginName();\nfunction bundledAssetPlatform() {\n return Capacitor.getPlatform() === 'ios' ? 'ios' : 'android';\n}\nfunction getConfiguredLocalConfig() {\n if (!Capacitor.isNativePlatform()) {\n return null;\n }\n const getServerUrl = Capacitor.getServerUrl;\n if (typeof getServerUrl !== 'function') {\n return null;\n }\n return parseBundledLocalConfig(getServerUrl());\n}\nfunction prepareUrlOptions(options) {\n assertValidBundledAssetPath(options.url);\n if (!Capacitor.isNativePlatform() || activePluginName !== PREVIOUS_PLUGIN_NAME) {\n return options;\n }\n return Object.assign(Object.assign({}, options), { url: resolveLegacyNativeWebViewUrl(options.url, bundledAssetPlatform(), getConfiguredLocalConfig()) });\n}\nconst baseInAppBrowser = registerPlugin(activePluginName, inAppBrowserImplementations);\nconst InAppBrowser = new Proxy(baseInAppBrowser, {\n get(target, prop, receiver) {\n if (prop === 'openWebView') {\n return (options) => target.openWebView(prepareUrlOptions(options));\n }\n if (prop === 'setUrl') {\n return (options) => target.setUrl(prepareUrlOptions(options));\n }\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === 'function') {\n return value.bind(target);\n }\n return value;\n },\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 errorMessage(error) {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === 'string') {\n return error;\n }\n if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n return error.message;\n }\n return String(error);\n}\nfunction isStaleProxyResponseError(error) {\n const message = errorMessage(error);\n return message.includes('No proxy handler found') || message.includes('Target WebView not found for proxy request');\n}\nfunction isProxyResponse(value) {\n return (value !== null &&\n typeof value === 'object' &&\n 'status' in value &&\n 'headers' in value &&\n !(value instanceof Response));\n}\nfunction isProxyRequestOverride(value) {\n return value !== null && typeof value === 'object' && 'url' in value && !(value instanceof Response);\n}\nfunction isProxyDecision(value) {\n return (value !== null && typeof value === 'object' && ('request' in value || 'response' in value || 'cancel' in value));\n}\nasync function sendProxyDecision(requestId, webviewId, decision, phase) {\n try {\n await InAppBrowser.handleProxyRequest({\n requestId,\n webviewId,\n decision,\n phase,\n });\n }\n catch (error) {\n if (isStaleProxyResponseError(error)) {\n return;\n }\n throw error;\n }\n}\nconst addProxyHandler = (callback) => {\n return InAppBrowser.addListener('proxyRequest', async (event) => {\n let decision = null;\n try {\n const result = await callback(event);\n if (result === null) {\n decision = null;\n }\n else if (isProxyDecision(result)) {\n decision = result;\n }\n else if (isProxyRequestOverride(result)) {\n decision = { request: result };\n }\n else if (isProxyResponse(result)) {\n decision = { response: result };\n }\n else {\n const cloned = result.clone();\n const buffer = await cloned.arrayBuffer();\n decision = {\n response: {\n body: arrayBufferToBase64(buffer),\n status: result.status,\n headers: headersToRecord(result.headers),\n },\n };\n }\n }\n catch (_error) {\n decision = null;\n }\n await sendProxyDecision(event.requestId, event.webviewId, decision, event.phase);\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 clearAllBrowsingData() {\n console.log('clearAllBrowsingData');\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(options) {\n console.log('close', options);\n return;\n }\n async hide(options) {\n console.log('hide', options);\n return;\n }\n async show(options) {\n console.log('show', options);\n return;\n }\n async sendToBack(options) {\n console.log('sendToBack not supported on web', options);\n return;\n }\n async bringToFront(options) {\n console.log('bringToFront not supported on web', options);\n return;\n }\n async dispatchInputEvent(options) {\n console.log('dispatchInputEvent not supported on web', options);\n return;\n }\n async setUrl(options) {\n console.log('setUrl', options.url);\n return;\n }\n async reload(options) {\n console.log('reload', options);\n return;\n }\n async postMessage(options) {\n console.log('postMessage', options);\n return options;\n }\n async takeScreenshot(options) {\n console.log('takeScreenshot not supported on web', options);\n throw this.unimplemented('Screenshots are not supported on web.');\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 handleProxyRequest(options) {\n console.log('handleProxyRequest not supported on web', options);\n return;\n }\n async setEnabledSafeTopMargin(options) {\n console.log('setEnabledSafeTopMargin not supported on web', options);\n return;\n }\n async setEnabledSafeBottomMargin(options) {\n console.log('setEnabledSafeBottomMargin not supported on web', options);\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 (!popup) {\n throw new Error('Failed to open secure window');\n }\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","CloseAction","Capacitor","registerPlugin","WebPlugin"],"mappings":"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"}
@@ -0,0 +1,188 @@
1
+ import Foundation
2
+ import ObjectiveC
3
+ import UniformTypeIdentifiers
4
+ import WebKit
5
+
6
+ final class BundledAssetSchemeHandler: NSObject, WKURLSchemeHandler {
7
+ private let basePath: String
8
+ private let expectedHost: String
9
+ private var activeTasks: [ObjectIdentifier: WKURLSchemeTask] = [:]
10
+ private let tasksLock = NSLock()
11
+
12
+ init(expectedHost: String) {
13
+ self.basePath = Self.resolveBasePath()
14
+ self.expectedHost = expectedHost.lowercased()
15
+ super.init()
16
+ }
17
+
18
+ func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
19
+ guard let requestURL = urlSchemeTask.request.url else {
20
+ urlSchemeTask.didFailWithError(
21
+ NSError(domain: "BundledAssetSchemeHandler", code: -1, userInfo: [NSLocalizedDescriptionKey: "Missing request URL"])
22
+ )
23
+ return
24
+ }
25
+
26
+ let taskID = ObjectIdentifier(urlSchemeTask)
27
+ tasksLock.lock()
28
+ activeTasks[taskID] = urlSchemeTask
29
+ tasksLock.unlock()
30
+
31
+ guard Self.isAllowedBundledAssetRequest(requestURL, expectedHost: expectedHost) else {
32
+ finish(task: urlSchemeTask, taskID: taskID) {
33
+ urlSchemeTask.didFailWithError(
34
+ NSError(
35
+ domain: "BundledAssetSchemeHandler",
36
+ code: 403,
37
+ userInfo: [NSLocalizedDescriptionKey: "Blocked bundled asset host: \(requestURL.absoluteString)"]
38
+ )
39
+ )
40
+ }
41
+ return
42
+ }
43
+
44
+ guard let filePath = BundledAssetSupport.routeAssetPath(for: requestURL.path, basePath: basePath) else {
45
+ finish(task: urlSchemeTask, taskID: taskID) {
46
+ urlSchemeTask.didFailWithError(
47
+ NSError(
48
+ domain: "BundledAssetSchemeHandler",
49
+ code: 403,
50
+ userInfo: [NSLocalizedDescriptionKey: "Blocked bundled asset path: \(requestURL.path)"]
51
+ )
52
+ )
53
+ }
54
+ return
55
+ }
56
+
57
+ let fileURL = URL(fileURLWithPath: filePath)
58
+
59
+ DispatchQueue.global(qos: .userInitiated).async { [weak self] in
60
+ guard let self else {
61
+ return
62
+ }
63
+
64
+ guard FileManager.default.fileExists(atPath: fileURL.path) else {
65
+ self.finish(task: urlSchemeTask, taskID: taskID) {
66
+ urlSchemeTask.didFailWithError(
67
+ NSError(
68
+ domain: "BundledAssetSchemeHandler",
69
+ code: 404,
70
+ userInfo: [NSLocalizedDescriptionKey: "Bundled asset not found: \(requestURL.path)"]
71
+ )
72
+ )
73
+ }
74
+ return
75
+ }
76
+
77
+ do {
78
+ let data = try Data(contentsOf: fileURL)
79
+ let mimeType = self.mimeType(for: requestURL.pathExtension)
80
+ let response = HTTPURLResponse(
81
+ url: requestURL,
82
+ statusCode: 200,
83
+ httpVersion: nil,
84
+ headerFields: [
85
+ "Content-Type": mimeType,
86
+ "Cache-Control": "no-cache"
87
+ ]
88
+ ) ?? URLResponse(url: requestURL, mimeType: mimeType, expectedContentLength: data.count, textEncodingName: nil)
89
+
90
+ self.finish(task: urlSchemeTask, taskID: taskID) {
91
+ urlSchemeTask.didReceive(response)
92
+ urlSchemeTask.didReceive(data)
93
+ urlSchemeTask.didFinish()
94
+ }
95
+ } catch {
96
+ self.finish(task: urlSchemeTask, taskID: taskID) {
97
+ urlSchemeTask.didFailWithError(error)
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
104
+ let taskID = ObjectIdentifier(urlSchemeTask)
105
+ tasksLock.lock()
106
+ activeTasks.removeValue(forKey: taskID)
107
+ tasksLock.unlock()
108
+ urlSchemeTask.stopped = true
109
+ }
110
+
111
+ private func finish(task: WKURLSchemeTask, taskID: ObjectIdentifier, block: @escaping () -> Void) {
112
+ DispatchQueue.main.async { [weak self] in
113
+ guard let self else {
114
+ return
115
+ }
116
+
117
+ guard !task.stopped else {
118
+ return
119
+ }
120
+
121
+ self.tasksLock.lock()
122
+ let isActive = self.activeTasks[taskID] != nil
123
+ if isActive {
124
+ self.activeTasks.removeValue(forKey: taskID)
125
+ }
126
+ self.tasksLock.unlock()
127
+
128
+ guard isActive, !task.stopped else {
129
+ return
130
+ }
131
+
132
+ block()
133
+ }
134
+ }
135
+
136
+ private static func isAllowedBundledAssetRequest(_ requestURL: URL, expectedHost: String) -> Bool {
137
+ guard let host = requestURL.host?.lowercased(), host == expectedHost else {
138
+ return false
139
+ }
140
+
141
+ return requestURL.port == nil
142
+ }
143
+
144
+ private func mimeType(for pathExtension: String) -> String {
145
+ if !pathExtension.isEmpty,
146
+ let uti = UTType(filenameExtension: pathExtension),
147
+ let mimeType = uti.preferredMIMEType {
148
+ return mimeType
149
+ }
150
+
151
+ return pathExtension.isEmpty ? "text/html" : "application/octet-stream"
152
+ }
153
+
154
+ private static func resolveBasePath() -> String {
155
+ if let publicDirectory = publicDirectoryURL(),
156
+ FileManager.default.fileExists(atPath: publicDirectory.path) {
157
+ return publicDirectory.path
158
+ }
159
+
160
+ if let wwwDirectory = wwwDirectoryURL(),
161
+ FileManager.default.fileExists(atPath: wwwDirectory.path) {
162
+ return wwwDirectory.path
163
+ }
164
+
165
+ return publicDirectoryURL()?.path ?? wwwDirectoryURL()?.path ?? ""
166
+ }
167
+
168
+ private static func publicDirectoryURL() -> URL? {
169
+ Bundle.main.resourceURL?.appendingPathComponent("public", isDirectory: true)
170
+ }
171
+
172
+ private static func wwwDirectoryURL() -> URL? {
173
+ Bundle.main.resourceURL?.appendingPathComponent("www", isDirectory: true)
174
+ }
175
+ }
176
+
177
+ private var bundledAssetStoppedKey: UInt8 = 0
178
+
179
+ private extension WKURLSchemeTask {
180
+ var stopped: Bool {
181
+ get {
182
+ objc_getAssociatedObject(self, &bundledAssetStoppedKey) as? Bool ?? false
183
+ }
184
+ set {
185
+ objc_setAssociatedObject(self, &bundledAssetStoppedKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
186
+ }
187
+ }
188
+ }
@@ -0,0 +1,221 @@
1
+ import Foundation
2
+
3
+ enum BundledAssetSupport {
4
+ struct LocalConfig: Equatable {
5
+ let scheme: String
6
+ let host: String
7
+ }
8
+
9
+ struct Resolution: Equatable {
10
+ let url: String
11
+ }
12
+
13
+ static let iosDefaults = LocalConfig(scheme: "capacitor", host: "localhost")
14
+ static let reservedWebKitSchemes = ["http", "https"]
15
+
16
+ static func parseLocalConfig(from localURL: URL?) -> LocalConfig? {
17
+ guard let localURL else {
18
+ return nil
19
+ }
20
+
21
+ guard let scheme = localURL.scheme?.lowercased(), !scheme.isEmpty else {
22
+ return nil
23
+ }
24
+
25
+ let host = localURL.host?.lowercased() ?? ""
26
+ guard !host.isEmpty else {
27
+ return nil
28
+ }
29
+
30
+ return LocalConfig(scheme: scheme, host: host)
31
+ }
32
+
33
+ static func handlerScheme(for localConfig: LocalConfig) -> String {
34
+ if reservedWebKitSchemes.contains(localConfig.scheme) {
35
+ return iosDefaults.scheme
36
+ }
37
+ return localConfig.scheme
38
+ }
39
+
40
+ static func resolve(_ urlString: String, localURL: URL?) -> Resolution? {
41
+ let trimmed = urlString.trimmingCharacters(in: .whitespacesAndNewlines)
42
+ let localConfig = parseLocalConfig(from: localURL) ?? iosDefaults
43
+ let navigationScheme = handlerScheme(for: localConfig)
44
+
45
+ if isRelativeBundledPath(trimmed) {
46
+ guard let path = normalizeBundledPath(trimmed) else {
47
+ return nil
48
+ }
49
+ return Resolution(url: "\(navigationScheme)://\(localConfig.host)\(path)")
50
+ }
51
+
52
+ if isBundledLocalURL(trimmed, localConfig: localConfig) {
53
+ if let rewritten = rewriteBundledLocalURL(trimmed, localConfig: localConfig, navigationScheme: navigationScheme) {
54
+ return Resolution(url: rewritten)
55
+ }
56
+ return Resolution(url: trimmed)
57
+ }
58
+
59
+ return Resolution(url: trimmed)
60
+ }
61
+
62
+ static func isBundledLocalURL(_ urlString: String, localConfig: LocalConfig) -> Bool {
63
+ guard let url = URL(string: urlString),
64
+ let scheme = url.scheme?.lowercased(),
65
+ let host = url.host?.lowercased() else {
66
+ return false
67
+ }
68
+
69
+ guard host == localConfig.host else {
70
+ return false
71
+ }
72
+
73
+ if url.port != nil {
74
+ return false
75
+ }
76
+
77
+ if scheme == localConfig.scheme || scheme == handlerScheme(for: localConfig) {
78
+ return true
79
+ }
80
+
81
+ return reservedWebKitSchemes.contains(scheme) && reservedWebKitSchemes.contains(localConfig.scheme)
82
+ }
83
+
84
+ static func isRelativeBundledPath(_ urlString: String) -> Bool {
85
+ let trimmed = urlString.trimmingCharacters(in: .whitespacesAndNewlines)
86
+ guard !trimmed.isEmpty else {
87
+ return false
88
+ }
89
+
90
+ return !isAbsoluteURL(trimmed)
91
+ }
92
+
93
+ private static let bundledAssetExtensions: Set<String> = [
94
+ "html", "htm", "js", "css", "json", "xml", "svg",
95
+ "png", "jpg", "jpeg", "gif", "webp", "woff", "woff2", "ttf", "map"
96
+ ]
97
+
98
+ static func isLikelyBundledRelativePath(_ urlString: String) -> Bool {
99
+ guard isRelativeBundledPath(urlString) else {
100
+ return false
101
+ }
102
+
103
+ let trimmed = stripPathQueryAndFragment(urlString.trimmingCharacters(in: .whitespacesAndNewlines))
104
+ if finalPathComponentStartsWithDot(trimmed) {
105
+ return false
106
+ }
107
+
108
+ if trimmed.hasPrefix("/") || trimmed.contains("/") {
109
+ return true
110
+ }
111
+
112
+ guard let dot = trimmed.lastIndex(of: ".") else {
113
+ return true
114
+ }
115
+
116
+ if dot == trimmed.startIndex {
117
+ return false
118
+ }
119
+
120
+ let extensionStart = trimmed.index(after: dot)
121
+ guard extensionStart < trimmed.endIndex else {
122
+ return false
123
+ }
124
+
125
+ let fileExtension = String(trimmed[extensionStart...]).lowercased()
126
+ return bundledAssetExtensions.contains(fileExtension)
127
+ }
128
+
129
+ private static func finalPathComponentStartsWithDot(_ path: String) -> Bool {
130
+ let finalComponent = path.split(separator: "/").last.map(String.init) ?? path
131
+ guard let first = finalComponent.first else {
132
+ return false
133
+ }
134
+ return first == "."
135
+ }
136
+
137
+ private static func stripPathQueryAndFragment(_ path: String) -> String {
138
+ let withoutQuery = path.split(separator: "?", maxSplits: 1, omittingEmptySubsequences: false).first.map(String.init) ?? path
139
+ return withoutQuery.split(separator: "#", maxSplits: 1, omittingEmptySubsequences: false).first.map(String.init) ?? withoutQuery
140
+ }
141
+
142
+ static func normalizeBundledPath(_ path: String) -> String? {
143
+ let trimmed = path.trimmingCharacters(in: .whitespacesAndNewlines)
144
+ if trimmed.isEmpty || trimmed == "/" {
145
+ return "/"
146
+ }
147
+
148
+ guard !containsPathTraversal(trimmed) else {
149
+ return nil
150
+ }
151
+
152
+ return trimmed.hasPrefix("/") ? trimmed : "/\(trimmed)"
153
+ }
154
+
155
+ static func routeAssetPath(for requestPath: String, basePath: String) -> String? {
156
+ guard !containsPathTraversal(requestPath) else {
157
+ return nil
158
+ }
159
+
160
+ let normalizedPath = requestPath.isEmpty ? "/" : requestPath
161
+ let relativePath: String
162
+ if URL(fileURLWithPath: normalizedPath).pathExtension.isEmpty {
163
+ relativePath = "/index.html"
164
+ } else {
165
+ relativePath = normalizedPath.hasPrefix("/") ? normalizedPath : "/\(normalizedPath)"
166
+ }
167
+
168
+ let resolvedURL = URL(fileURLWithPath: basePath).appendingPathComponent(relativePath, isDirectory: false).standardizedFileURL
169
+ let baseURL = URL(fileURLWithPath: basePath).standardizedFileURL
170
+ let resolvedPath = resolvedURL.path
171
+ let basePathValue = baseURL.path
172
+
173
+ guard resolvedPath == basePathValue || resolvedPath.hasPrefix(basePathValue + "/") else {
174
+ return nil
175
+ }
176
+
177
+ return resolvedPath
178
+ }
179
+
180
+ static func containsPathTraversal(_ path: String) -> Bool {
181
+ path.split(separator: "/").contains(where: { $0 == ".." })
182
+ }
183
+
184
+ private static func rewriteBundledLocalURL(
185
+ _ urlString: String,
186
+ localConfig: LocalConfig,
187
+ navigationScheme: String
188
+ ) -> String? {
189
+ guard let url = URL(string: urlString),
190
+ let host = url.host?.lowercased(),
191
+ host == localConfig.host else {
192
+ return nil
193
+ }
194
+
195
+ guard let scheme = url.scheme?.lowercased(), scheme != navigationScheme else {
196
+ return nil
197
+ }
198
+
199
+ var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
200
+ components?.scheme = navigationScheme
201
+ return components?.url?.absoluteString
202
+ }
203
+
204
+ private static func isAbsoluteURL(_ urlString: String) -> Bool {
205
+ if urlString.hasPrefix("//") {
206
+ return true
207
+ }
208
+
209
+ guard let colonIndex = urlString.firstIndex(of: ":"),
210
+ colonIndex > urlString.startIndex else {
211
+ return false
212
+ }
213
+
214
+ let scheme = urlString[..<colonIndex]
215
+ guard let first = scheme.first, first.isLetter else {
216
+ return false
217
+ }
218
+
219
+ return scheme.allSatisfy { $0.isLetter || $0.isNumber || $0 == "+" || $0 == "-" || $0 == "." }
220
+ }
221
+ }
@@ -415,7 +415,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
415
415
  case aware = "AWARE"
416
416
  case fakeVisible = "FAKE_VISIBLE"
417
417
  }
418
- private let pluginVersion: String = "8.14.3"
418
+ private let pluginVersion: String = "8.15.0"
419
419
  public let identifier = "CapgoInAppBrowserPlugin"
420
420
  public let jsName = "CapgoInAppBrowser"
421
421
  public let pluginMethods: [CAPPluginMethod] = [
@@ -1226,12 +1226,24 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1226
1226
  throw optionError("Failed to load \(optionName) icon: \(icon)")
1227
1227
  }
1228
1228
 
1229
+ private func bundledAssetLocalConfig() -> BundledAssetSupport.LocalConfig {
1230
+ BundledAssetSupport.parseLocalConfig(from: self.bridge?.config.localURL) ?? BundledAssetSupport.iosDefaults
1231
+ }
1232
+
1233
+ private func applyBundledAssetSettings(to webViewController: WKWebViewController) {
1234
+ // Scheme handlers are registered once during initWebview; localURL is fixed for the app lifetime.
1235
+ let localConfig = bundledAssetLocalConfig()
1236
+ webViewController.bundledAssetLocalScheme = BundledAssetSupport.handlerScheme(for: localConfig)
1237
+ webViewController.bundledAssetLocalHost = localConfig.host
1238
+ }
1239
+
1229
1240
  private func webSource(for urlString: String) -> WKWebSource? {
1230
1241
  if let html = HtmlDataUrlSupport.parseHtml(from: urlString) {
1231
1242
  return .string(html, base: nil)
1232
1243
  }
1233
1244
 
1234
- guard let url = URL(string: urlString) else {
1245
+ guard let resolution = BundledAssetSupport.resolve(urlString, localURL: self.bridge?.config.localURL),
1246
+ let url = URL(string: resolution.url) else {
1235
1247
  return nil
1236
1248
  }
1237
1249
 
@@ -1442,7 +1454,8 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1442
1454
  }
1443
1455
 
1444
1456
  DispatchQueue.main.async {
1445
- guard let webSource = self.webSource(for: urlString) else {
1457
+ let webSourceResult = self.webSource(for: urlString)
1458
+ guard let webSource = webSourceResult else {
1446
1459
  call.reject("Invalid URL format")
1447
1460
  return
1448
1461
  }
@@ -1495,6 +1508,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1495
1508
  authorizedAppLinks: authorizedAppLinks,
1496
1509
  openBlankTargetInWebView: openBlankTargetInWebView
1497
1510
  )
1511
+ self.applyBundledAssetSettings(to: webViewController)
1498
1512
  webViewController.enableReloadGesture = enableReloadGesture
1499
1513
  webViewController.disableOverscroll = disableOverscroll
1500
1514
  webViewController.initWebview(isInspectable: isInspectable)
@@ -1846,11 +1860,14 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1846
1860
  return
1847
1861
  }
1848
1862
 
1849
- guard let url = URL(string: urlString) else {
1863
+ guard let resolution = BundledAssetSupport.resolve(urlString, localURL: self.bridge?.config.localURL),
1864
+ let url = URL(string: resolution.url) else {
1850
1865
  call.reject("Invalid URL")
1851
1866
  return
1852
1867
  }
1853
1868
 
1869
+ self.applyBundledAssetSettings(to: webViewController)
1870
+
1854
1871
  webViewController.source = .remote(url)
1855
1872
  webViewController.load(remote: url)
1856
1873
  call.resolve()
@@ -2357,6 +2374,11 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
2357
2374
  return
2358
2375
  }
2359
2376
 
2377
+ if BundledAssetSupport.isLikelyBundledRelativePath(urlString) {
2378
+ call.reject("Bundled assets require openWebView()")
2379
+ return
2380
+ }
2381
+
2360
2382
  guard let url = URL(string: urlString),
2361
2383
  let scheme = url.scheme?.lowercased(),
2362
2384
  ["http", "https"].contains(scheme) else {
@@ -482,6 +482,9 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
482
482
  var disableOverscroll: Bool = false
483
483
  var proxyRequests: Bool = false
484
484
  var proxySchemeHandler: ProxySchemeHandler?
485
+ var bundledAssetSchemeHandler: BundledAssetSchemeHandler?
486
+ var bundledAssetLocalScheme: String = BundledAssetSupport.iosDefaults.scheme
487
+ var bundledAssetLocalHost: String = BundledAssetSupport.iosDefaults.host
485
488
  var proxyBridge: ProxyBridge?
486
489
  var proxyBridgeAccessToken: String?
487
490
  var legacyProxyRequestURLRegexPattern: String?
@@ -2065,6 +2068,12 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
2065
2068
  }
2066
2069
  }
2067
2070
 
2071
+ let bundledAssetHandler = BundledAssetSchemeHandler(expectedHost: bundledAssetLocalHost)
2072
+ self.bundledAssetSchemeHandler = bundledAssetHandler
2073
+ if webConfiguration.urlSchemeHandler(forURLScheme: bundledAssetLocalScheme) == nil {
2074
+ webConfiguration.setURLSchemeHandler(bundledAssetHandler, forURLScheme: bundledAssetLocalScheme)
2075
+ }
2076
+
2068
2077
  if ProxyBridgeSupport.shouldInjectBridge(hasProxySchemeHandler: proxySchemeHandler != nil) {
2069
2078
  addProxyBridgeUserScripts(to: userContentController)
2070
2079
  }
@@ -2309,6 +2318,8 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
2309
2318
  self.disableOverscroll = parent.disableOverscroll
2310
2319
  self.proxyRequests = parent.proxyRequests
2311
2320
  self.proxySchemeHandler = proxySchemeHandler
2321
+ self.bundledAssetLocalScheme = parent.bundledAssetLocalScheme
2322
+ self.bundledAssetLocalHost = parent.bundledAssetLocalHost
2312
2323
  self.proxyBridge = parent.proxyBridge
2313
2324
  self.proxyBridgeAccessToken = parent.proxyBridgeAccessToken
2314
2325
  self.legacyProxyRequestURLRegexPattern = parent.legacyProxyRequestURLRegexPattern
@@ -2981,6 +2992,16 @@ fileprivate extension WKWebViewController {
2981
2992
  return
2982
2993
  }
2983
2994
 
2995
+ let bundledLocalConfig = BundledAssetSupport.LocalConfig(
2996
+ scheme: bundledAssetLocalScheme,
2997
+ host: bundledAssetLocalHost
2998
+ )
2999
+ if BundledAssetSupport.isBundledLocalURL(url.absoluteString, localConfig: bundledLocalConfig) {
3000
+ print("[InAppBrowser] bundled local asset URL detected, allowing navigation")
3001
+ completion(false)
3002
+ return
3003
+ }
3004
+
2984
3005
  // Handle all non-http(s) schemes by default
2985
3006
  if scheme != "http" && scheme != "https" && scheme != "file" {
2986
3007
  print("[InAppBrowser] not http(s) scheme, try to open URLs in external apps")