@capgo/inappbrowser 8.1.26 → 8.3.0-alpha.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.
- package/README.md +142 -32
- package/android/src/main/assets/proxy-bridge.js +197 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +95 -26
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +5 -7
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/ProxyBridge.java +60 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewCallbacks.java +2 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +262 -165
- package/dist/docs.json +258 -3
- package/dist/esm/definitions.d.ts +120 -3
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +20 -2
- package/dist/esm/index.js +79 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +1 -0
- package/dist/esm/web.js +4 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +83 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +83 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/InAppBrowserPlugin/InAppBrowserPlugin.swift +64 -1
- package/ios/Sources/InAppBrowserPlugin/ProxySchemeHandler.swift +257 -0
- package/ios/Sources/InAppBrowserPlugin/WKWebView+SchemeHandling.swift +53 -0
- package/ios/Sources/InAppBrowserPlugin/WKWebViewController.swift +18 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
# @capgo/inappbrowser
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
<a href="https://capgo.app/">
|
|
4
|
+
<img
|
|
5
|
+
src="https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png"
|
|
6
|
+
alt="Capgo - Instant updates for capacitor"
|
|
7
|
+
/>
|
|
8
|
+
</a>
|
|
3
9
|
|
|
4
10
|
<div align="center">
|
|
5
|
-
<h2
|
|
6
|
-
|
|
11
|
+
<h2>
|
|
12
|
+
<a href="https://capgo.app/?ref=plugin_inappbrowser"> ➡️ Get Instant updates for your App with Capgo</a>
|
|
13
|
+
</h2>
|
|
14
|
+
<h2>
|
|
15
|
+
<a href="https://capgo.app/consulting/?ref=plugin_inappbrowser">
|
|
16
|
+
{' '}
|
|
17
|
+
Missing a feature? We’ll build the plugin for you 💪
|
|
18
|
+
</a>
|
|
19
|
+
</h2>
|
|
7
20
|
</div>
|
|
8
21
|
|
|
9
22
|
Capacitor plugin in app browser with urlChangeEvent, two way communication, camera and microphone usage, etc.
|
|
@@ -30,10 +43,10 @@ The most complete doc is available here: https://capgo.app/docs/plugins/inappbro
|
|
|
30
43
|
|
|
31
44
|
| Plugin version | Capacitor compatibility | Maintained |
|
|
32
45
|
| -------------- | ----------------------- | ---------- |
|
|
33
|
-
| v8.\*.\* | v8.\*.\* | ✅
|
|
34
|
-
| v7.\*.\* | v7.\*.\* | On demand
|
|
35
|
-
| v6.\*.\* | v6.\*.\* | ❌
|
|
36
|
-
| v5.\*.\* | v5.\*.\* | ❌
|
|
46
|
+
| v8.\*.\* | v8.\*.\* | ✅ |
|
|
47
|
+
| v7.\*.\* | v7.\*.\* | On demand |
|
|
48
|
+
| v6.\*.\* | v6.\*.\* | ❌ |
|
|
49
|
+
| v5.\*.\* | v5.\*.\* | ❌ |
|
|
37
50
|
|
|
38
51
|
> **Note:** The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation (e.g., plugin v8 for Capacitor 8). Only the latest major version is actively maintained.
|
|
39
52
|
|
|
@@ -43,28 +56,50 @@ The most complete doc is available here: https://capgo.app/docs/plugins/inappbro
|
|
|
43
56
|
npm install @capgo/inappbrowser
|
|
44
57
|
npx cap sync
|
|
45
58
|
```
|
|
59
|
+
|
|
46
60
|
## Usage
|
|
47
61
|
|
|
62
|
+
```js
|
|
63
|
+
import { InAppBrowser } from '@capgo/inappbrowser';
|
|
64
|
+
|
|
65
|
+
InAppBrowser.open({ url: 'YOUR_URL' });
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Customize Chrome Custom Tab Appearance (Android)
|
|
69
|
+
|
|
70
|
+
The `open()` method launches a Chrome Custom Tab on Android. You can customize its appearance to blend with your app:
|
|
71
|
+
|
|
48
72
|
```js
|
|
49
73
|
import { InAppBrowser } from '@capgo/inappbrowser'
|
|
50
74
|
|
|
51
|
-
InAppBrowser.open({
|
|
75
|
+
InAppBrowser.open({
|
|
76
|
+
url: "https://example.com",
|
|
77
|
+
toolbarColor: "#1A1A2E", // Match your app's theme
|
|
78
|
+
showTitle: true, // Show page title instead of raw URL
|
|
79
|
+
showArrow: true, // Back arrow instead of X close icon
|
|
80
|
+
urlBarHidingEnabled: true, // Auto-hide URL bar on scroll
|
|
81
|
+
disableShare: true, // Remove share from overflow menu
|
|
82
|
+
disableBookmark: true, // Hide bookmark icon (undocumented, may break)
|
|
83
|
+
disableDownload: true, // Hide download icon (undocumented, may break)
|
|
84
|
+
});
|
|
52
85
|
```
|
|
53
86
|
|
|
87
|
+
All CCT options are Android-only and safely ignored on iOS. See [`OpenOptions`](#openoptions) for full documentation.
|
|
88
|
+
|
|
54
89
|
### Open WebView with Custom Dimensions
|
|
55
90
|
|
|
56
91
|
By default, the webview opens in fullscreen. You can set custom dimensions to control the size and position:
|
|
57
92
|
|
|
58
93
|
```js
|
|
59
|
-
import { InAppBrowser } from '@capgo/inappbrowser'
|
|
94
|
+
import { InAppBrowser } from '@capgo/inappbrowser';
|
|
60
95
|
|
|
61
96
|
// Open with custom dimensions (400x600 at position 50,100)
|
|
62
97
|
const { id } = await InAppBrowser.openWebView({
|
|
63
|
-
url:
|
|
98
|
+
url: 'YOUR_URL',
|
|
64
99
|
width: 400,
|
|
65
100
|
height: 600,
|
|
66
101
|
x: 50,
|
|
67
|
-
y: 100
|
|
102
|
+
y: 100,
|
|
68
103
|
});
|
|
69
104
|
|
|
70
105
|
// Update dimensions at runtime
|
|
@@ -73,7 +108,7 @@ InAppBrowser.updateDimensions({
|
|
|
73
108
|
width: 500,
|
|
74
109
|
height: 700,
|
|
75
110
|
x: 100,
|
|
76
|
-
y: 150
|
|
111
|
+
y: 150,
|
|
77
112
|
});
|
|
78
113
|
```
|
|
79
114
|
|
|
@@ -84,11 +119,11 @@ InAppBrowser.updateDimensions({
|
|
|
84
119
|
To create a webView with a 20px bottom margin (safe margin area outside the browser):
|
|
85
120
|
|
|
86
121
|
```js
|
|
87
|
-
import { InAppBrowser } from '@capgo/inappbrowser'
|
|
122
|
+
import { InAppBrowser } from '@capgo/inappbrowser';
|
|
88
123
|
|
|
89
124
|
InAppBrowser.openWebView({
|
|
90
|
-
url:
|
|
91
|
-
enabledSafeBottomMargin: true
|
|
125
|
+
url: 'YOUR_URL',
|
|
126
|
+
enabledSafeBottomMargin: true,
|
|
92
127
|
});
|
|
93
128
|
```
|
|
94
129
|
|
|
@@ -99,15 +134,16 @@ Web platform is not supported. Use `window.open` instead.
|
|
|
99
134
|
To open the webview in true full screen mode (content extends behind the status bar), set `enabledSafeTopMargin` to `false`:
|
|
100
135
|
|
|
101
136
|
```js
|
|
102
|
-
import { InAppBrowser } from '@capgo/inappbrowser'
|
|
137
|
+
import { InAppBrowser } from '@capgo/inappbrowser';
|
|
103
138
|
|
|
104
139
|
InAppBrowser.openWebView({
|
|
105
|
-
url:
|
|
106
|
-
enabledSafeTopMargin: false
|
|
140
|
+
url: 'YOUR_URL',
|
|
141
|
+
enabledSafeTopMargin: false, // Disables safe area at top, allows full screen
|
|
107
142
|
});
|
|
108
143
|
```
|
|
109
144
|
|
|
110
145
|
This option works independently of the toolbar type:
|
|
146
|
+
|
|
111
147
|
- **iOS**: The webview extends behind the status bar, providing true edge-to-edge content
|
|
112
148
|
- **Android**: The top margin is disabled, allowing content to fill the entire screen
|
|
113
149
|
|
|
@@ -193,16 +229,16 @@ With this plugin you can send events from the main app to the inappbrowser and v
|
|
|
193
229
|
#### Main app to inappbrowser, detail object is mendatory
|
|
194
230
|
|
|
195
231
|
```js
|
|
196
|
-
const { id } = await InAppBrowser.openWebView({ url:
|
|
197
|
-
InAppBrowser.postMessage({ id, detail: { message:
|
|
232
|
+
const { id } = await InAppBrowser.openWebView({ url: 'YOUR_URL' });
|
|
233
|
+
InAppBrowser.postMessage({ id, detail: { message: 'myMessage' } });
|
|
198
234
|
// Or broadcast to all open webviews
|
|
199
|
-
InAppBrowser.postMessage({ detail: { message:
|
|
235
|
+
InAppBrowser.postMessage({ detail: { message: 'broadcast' } });
|
|
200
236
|
```
|
|
201
237
|
|
|
202
238
|
#### Receive event from native in the inappbrowser
|
|
203
239
|
|
|
204
240
|
```js
|
|
205
|
-
window.addEventListener(
|
|
241
|
+
window.addEventListener('messageFromNative', (event) => {
|
|
206
242
|
console.log(event);
|
|
207
243
|
});
|
|
208
244
|
```
|
|
@@ -210,13 +246,13 @@ window.addEventListener("messageFromNative", (event) => {
|
|
|
210
246
|
#### Send event from inappbrowser to main app, detail object is mendatory
|
|
211
247
|
|
|
212
248
|
```js
|
|
213
|
-
window.mobileApp.postMessage({ detail: { message:
|
|
249
|
+
window.mobileApp.postMessage({ detail: { message: 'myMessage' } });
|
|
214
250
|
```
|
|
215
251
|
|
|
216
252
|
#### Receive event from inappbrowser in the main app
|
|
217
253
|
|
|
218
254
|
```js
|
|
219
|
-
InAppBrowser.addListener(
|
|
255
|
+
InAppBrowser.addListener('messageFromWebview', (event) => {
|
|
220
256
|
console.log(event.id, event.detail);
|
|
221
257
|
});
|
|
222
258
|
```
|
|
@@ -251,6 +287,8 @@ window.mobileApp.close();
|
|
|
251
287
|
* [`addListener('messageFromWebview', ...)`](#addlistenermessagefromwebview-)
|
|
252
288
|
* [`addListener('browserPageLoaded', ...)`](#addlistenerbrowserpageloaded-)
|
|
253
289
|
* [`addListener('pageLoadError', ...)`](#addlistenerpageloaderror-)
|
|
290
|
+
* [`addListener('proxyRequest', ...)`](#addlistenerproxyrequest-)
|
|
291
|
+
* [`handleProxyRequest(...)`](#handleproxyrequest)
|
|
254
292
|
* [`removeAllListeners()`](#removealllisteners)
|
|
255
293
|
* [`reload(...)`](#reload)
|
|
256
294
|
* [`updateDimensions(...)`](#updatedimensions)
|
|
@@ -635,6 +673,45 @@ Will be triggered when page load error
|
|
|
635
673
|
--------------------
|
|
636
674
|
|
|
637
675
|
|
|
676
|
+
### addListener('proxyRequest', ...)
|
|
677
|
+
|
|
678
|
+
```typescript
|
|
679
|
+
addListener(eventName: 'proxyRequest', listenerFunc: (event: ProxyRequest) => void) => Promise<PluginListenerHandle>
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
Listen for proxied requests from the in-app browser webview.
|
|
683
|
+
Use addProxyHandler() wrapper instead of calling this directly.
|
|
684
|
+
|
|
685
|
+
| Param | Type |
|
|
686
|
+
| ------------------ | ------------------------------------------------------------------------- |
|
|
687
|
+
| **`eventName`** | <code>'proxyRequest'</code> |
|
|
688
|
+
| **`listenerFunc`** | <code>(event: <a href="#proxyrequest">ProxyRequest</a>) => void</code> |
|
|
689
|
+
|
|
690
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>></code>
|
|
691
|
+
|
|
692
|
+
**Since:** 9.0.0
|
|
693
|
+
|
|
694
|
+
--------------------
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
### handleProxyRequest(...)
|
|
698
|
+
|
|
699
|
+
```typescript
|
|
700
|
+
handleProxyRequest(options: { requestId: string; response: ProxyResponse | null; webviewId?: string; }) => Promise<void>
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
Internal method: sends a proxied response back to native.
|
|
704
|
+
Called by addProxyHandler() wrapper — not intended for direct use.
|
|
705
|
+
|
|
706
|
+
| Param | Type |
|
|
707
|
+
| ------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
708
|
+
| **`options`** | <code>{ requestId: string; response: <a href="#proxyresponse">ProxyResponse</a> \| null; webviewId?: string; }</code> |
|
|
709
|
+
|
|
710
|
+
**Since:** 9.0.0
|
|
711
|
+
|
|
712
|
+
--------------------
|
|
713
|
+
|
|
714
|
+
|
|
638
715
|
### removeAllListeners()
|
|
639
716
|
|
|
640
717
|
```typescript
|
|
@@ -746,11 +823,18 @@ And in the AndroidManifest.xml file:
|
|
|
746
823
|
|
|
747
824
|
#### OpenOptions
|
|
748
825
|
|
|
749
|
-
| Prop | Type | Description
|
|
750
|
-
| ---------------------------- | -------------------- |
|
|
751
|
-
| **`url`** | <code>string</code> | Target URL to load.
|
|
752
|
-
| **`isPresentAfterPageLoad`** | <code>boolean</code> | if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately.
|
|
753
|
-
| **`preventDeeplink`** | <code>boolean</code> | if true the deeplink will not be opened, if false the deeplink will be opened when clicked on the link
|
|
826
|
+
| Prop | Type | Description | Default | Since |
|
|
827
|
+
| ---------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
|
|
828
|
+
| **`url`** | <code>string</code> | Target URL to load. | | 0.1.0 |
|
|
829
|
+
| **`isPresentAfterPageLoad`** | <code>boolean</code> | if true, the browser will be presented after the page is loaded, if false, the browser will be presented immediately. | | 0.1.0 |
|
|
830
|
+
| **`preventDeeplink`** | <code>boolean</code> | if true the deeplink will not be opened, if false the deeplink will be opened when clicked on the link | | 0.1.0 |
|
|
831
|
+
| **`toolbarColor`** | <code>string</code> | Toolbar background color in hex format (e.g., "#1A1A2E"). Applied to both light and dark color schemes. Also sets the navigation bar color to match. **Android only** — ignored on iOS. | | 8.2.0 |
|
|
832
|
+
| **`urlBarHidingEnabled`** | <code>boolean</code> | Whether the URL bar should auto-hide when the user scrolls down. The bar reappears on any upward scroll. **Android only** — ignored on iOS. | <code>false</code> | 8.2.0 |
|
|
833
|
+
| **`showTitle`** | <code>boolean</code> | Show the page's HTML <title> in the toolbar instead of the raw URL. The true URL is still visible when the user taps the title area. **Android only** — ignored on iOS. | <code>false</code> | 8.2.0 |
|
|
834
|
+
| **`showArrow`** | <code>boolean</code> | Replace the default "X" close icon with a back arrow. Makes the Custom Tab feel like a native navigation push rather than a modal overlay. **Android only** — ignored on iOS. | <code>false</code> | 8.2.0 |
|
|
835
|
+
| **`disableShare`** | <code>boolean</code> | Remove the share action from the overflow menu. **Android only** — ignored on iOS. | <code>false</code> | 8.2.0 |
|
|
836
|
+
| **`disableBookmark`** | <code>boolean</code> | Hide the bookmark star icon in the overflow menu. Uses an undocumented Chromium intent extra — may stop working on future Chrome updates. **Android only** — ignored on iOS. | <code>false</code> | 8.2.0 |
|
|
837
|
+
| **`disableDownload`** | <code>boolean</code> | Hide the download icon in the overflow menu. Uses an undocumented Chromium intent extra — may stop working on future Chrome updates. **Android only** — ignored on iOS. | <code>false</code> | 8.2.0 |
|
|
754
838
|
|
|
755
839
|
|
|
756
840
|
#### ClearCookieOptions
|
|
@@ -820,7 +904,7 @@ And in the AndroidManifest.xml file:
|
|
|
820
904
|
| **`ignoreUntrustedSSLError`** | <code>boolean</code> | ignoreUntrustedSSLError: if true, the webview will ignore untrusted SSL errors allowing the user to view the website. | <code>false</code> | 6.1.0 |
|
|
821
905
|
| **`preShowScript`** | <code>string</code> | preShowScript: if isPresentAfterPageLoad is true and this variable is set the plugin will inject a script before showing the browser. This script will be run in an async context. The plugin will wait for the script to finish (max 10 seconds) | | 6.6.0 |
|
|
822
906
|
| **`preShowScriptInjectionTime`** | <code>'documentStart' \| 'pageLoad'</code> | preShowScriptInjectionTime: controls when the preShowScript is injected. - "documentStart": injects before any page JavaScript runs (good for polyfills like Firebase) - "pageLoad": injects after page load (default, original behavior) | <code>"pageLoad"</code> | 7.26.0 |
|
|
823
|
-
| **`proxyRequests`** | <code>
|
|
907
|
+
| **`proxyRequests`** | <code>boolean</code> | When true, all HTTP/HTTPS requests from the webview are sent to the proxy handler registered via addProxyHandler(). The handler can return a custom Response or null for pass-through. | | 9.0.0 |
|
|
824
908
|
| **`buttonNearDone`** | <code>{ ios: { iconType: 'sf-symbol' \| 'asset'; icon: string; }; android: { iconType: 'asset' \| 'vector'; icon: string; width?: number; height?: number; }; }</code> | buttonNearDone allows for a creation of a custom button near the done/close button. The button is only shown when toolbarType is not "activity", "navigation", or "blank". For Android: - iconType must be "asset" - icon path should be in the public folder (e.g. "monkey.svg") - width and height are optional, defaults to 48dp - button is positioned at the end of toolbar with 8dp margin For iOS: - iconType can be "sf-symbol" or "asset" - for sf-symbol, icon should be the symbol name - for asset, icon should be the asset name | | 6.7.0 |
|
|
825
909
|
| **`textZoom`** | <code>number</code> | textZoom: sets the text zoom of the page in percent. Allows users to increase or decrease the text size for better readability. | <code>100</code> | 7.6.0 |
|
|
826
910
|
| **`preventDeeplink`** | <code>boolean</code> | preventDeeplink: if true, the deeplink will not be opened, if false the deeplink will be opened when clicked on the link. on IOS each schema need to be added to info.plist file under LSApplicationQueriesSchemes when false to make it work. | <code>false</code> | 0.1.0 |
|
|
@@ -883,6 +967,31 @@ And in the AndroidManifest.xml file:
|
|
|
883
967
|
| **`url`** | <code>string</code> | Emit when a button is clicked. | 0.0.1 |
|
|
884
968
|
|
|
885
969
|
|
|
970
|
+
#### ProxyRequest
|
|
971
|
+
|
|
972
|
+
Represents an intercepted HTTP request from the in-app browser webview.
|
|
973
|
+
|
|
974
|
+
| Prop | Type | Description |
|
|
975
|
+
| --------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
976
|
+
| **`requestId`** | <code>string</code> | Unique identifier for this request, used to match responses |
|
|
977
|
+
| **`url`** | <code>string</code> | The full URL being requested |
|
|
978
|
+
| **`method`** | <code>string</code> | HTTP method (GET, POST, PUT, DELETE, etc.) |
|
|
979
|
+
| **`headers`** | <code><a href="#record">Record</a><string, string></code> | Request headers as key-value pairs |
|
|
980
|
+
| **`body`** | <code>string \| null</code> | Base64-encoded request body, or null if no body. On Android, requests from HTML elements (img, script, link, iframe) are intercepted natively and do not have access to the request body — this field will be empty for those requests. Requests from fetch() and XMLHttpRequest include the full body. |
|
|
981
|
+
| **`webviewId`** | <code>string</code> | ID of the webview that made this request |
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
#### ProxyResponse
|
|
985
|
+
|
|
986
|
+
Response to send back for a proxied request.
|
|
987
|
+
|
|
988
|
+
| Prop | Type | Description |
|
|
989
|
+
| ------------- | --------------------------------------------------------------- | ----------------------------------- |
|
|
990
|
+
| **`body`** | <code>string</code> | Base64-encoded response body |
|
|
991
|
+
| **`status`** | <code>number</code> | HTTP status code |
|
|
992
|
+
| **`headers`** | <code><a href="#record">Record</a><string, string></code> | Response headers as key-value pairs |
|
|
993
|
+
|
|
994
|
+
|
|
886
995
|
#### DimensionOptions
|
|
887
996
|
|
|
888
997
|
| Prop | Type | Description |
|
|
@@ -996,5 +1105,6 @@ Construct a type with a set of properties K of type T
|
|
|
996
1105
|
</docgen-api>
|
|
997
1106
|
|
|
998
1107
|
**Credits**
|
|
999
|
-
|
|
1000
|
-
|
|
1108
|
+
|
|
1109
|
+
- [WKWebViewController](https://github.com/Meniny/WKWebViewController) - for iOS
|
|
1110
|
+
- [CapBrowser](https://github.com/gadapa-rakesh/CapBrowser) - For the base in capacitor v2
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(() => {
|
|
3
|
+
var __async = (__this, __arguments, generator) => {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
var fulfilled = (value) => {
|
|
6
|
+
try {
|
|
7
|
+
step(generator.next(value));
|
|
8
|
+
} catch (e) {
|
|
9
|
+
reject(e);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var rejected = (value) => {
|
|
13
|
+
try {
|
|
14
|
+
step(generator.throw(value));
|
|
15
|
+
} catch (e) {
|
|
16
|
+
reject(e);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
20
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// src/proxy-bridge.ts
|
|
25
|
+
(function() {
|
|
26
|
+
const proxyBridge = window.__capgoProxy;
|
|
27
|
+
if (!proxyBridge) return;
|
|
28
|
+
const accessToken = "___CAPGO_PROXY_TOKEN___";
|
|
29
|
+
let requestCounter = 0;
|
|
30
|
+
function generateRequestId() {
|
|
31
|
+
return "pr_" + Date.now() + "_" + requestCounter++;
|
|
32
|
+
}
|
|
33
|
+
function arrayBufferToBase64(buffer) {
|
|
34
|
+
const bytes = new Uint8Array(buffer);
|
|
35
|
+
let binary = "";
|
|
36
|
+
for (let i = 0; i < bytes.byteLength; i++) {
|
|
37
|
+
binary += String.fromCharCode(bytes[i]);
|
|
38
|
+
}
|
|
39
|
+
return btoa(binary);
|
|
40
|
+
}
|
|
41
|
+
function stringToBase64(str) {
|
|
42
|
+
return btoa(unescape(encodeURIComponent(str)));
|
|
43
|
+
}
|
|
44
|
+
function resolveUrl(url) {
|
|
45
|
+
if (url && !url.match(/^[a-zA-Z][a-zA-Z0-9+\-.]*:\/\//)) {
|
|
46
|
+
try {
|
|
47
|
+
return new URL(url, window.location.href).href;
|
|
48
|
+
} catch (_e) {
|
|
49
|
+
return url;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return url;
|
|
53
|
+
}
|
|
54
|
+
function bodyToBase64(body) {
|
|
55
|
+
return __async(this, null, function* () {
|
|
56
|
+
if (body === null || body === void 0) return null;
|
|
57
|
+
if (typeof body === "string") return stringToBase64(body);
|
|
58
|
+
if (body instanceof ArrayBuffer) return arrayBufferToBase64(body);
|
|
59
|
+
if (ArrayBuffer.isView(body))
|
|
60
|
+
return arrayBufferToBase64(body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength));
|
|
61
|
+
if (body instanceof Blob) {
|
|
62
|
+
const ab = yield body.arrayBuffer();
|
|
63
|
+
return arrayBufferToBase64(ab);
|
|
64
|
+
}
|
|
65
|
+
if (body instanceof FormData) {
|
|
66
|
+
const ab = yield new Response(body).arrayBuffer();
|
|
67
|
+
return arrayBufferToBase64(ab);
|
|
68
|
+
}
|
|
69
|
+
if (body instanceof URLSearchParams) {
|
|
70
|
+
return stringToBase64(body.toString());
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const originalFetch = window.fetch;
|
|
76
|
+
window.fetch = function(input, init) {
|
|
77
|
+
return __async(this, null, function* () {
|
|
78
|
+
const requestId = generateRequestId();
|
|
79
|
+
let url;
|
|
80
|
+
let method = "GET";
|
|
81
|
+
const headers = {};
|
|
82
|
+
let body = null;
|
|
83
|
+
if (input instanceof Request) {
|
|
84
|
+
url = input.url;
|
|
85
|
+
method = input.method;
|
|
86
|
+
input.headers.forEach((v, k) => {
|
|
87
|
+
headers[k] = v;
|
|
88
|
+
});
|
|
89
|
+
try {
|
|
90
|
+
const cloned = input.clone();
|
|
91
|
+
const ab = yield cloned.arrayBuffer();
|
|
92
|
+
if (ab.byteLength > 0) {
|
|
93
|
+
body = ab;
|
|
94
|
+
}
|
|
95
|
+
} catch (_e) {
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
url = input instanceof URL ? input.toString() : input;
|
|
99
|
+
}
|
|
100
|
+
url = resolveUrl(url);
|
|
101
|
+
if (init) {
|
|
102
|
+
if (init.method) method = init.method;
|
|
103
|
+
if (init.headers) {
|
|
104
|
+
const h = new Headers(init.headers);
|
|
105
|
+
h.forEach((v, k) => {
|
|
106
|
+
headers[k] = v;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (init.body !== void 0) body = init.body;
|
|
110
|
+
}
|
|
111
|
+
if (body instanceof FormData) {
|
|
112
|
+
const encoded = new Response(body);
|
|
113
|
+
const ct = encoded.headers.get("content-type");
|
|
114
|
+
if (ct) {
|
|
115
|
+
Object.keys(headers).forEach((k) => {
|
|
116
|
+
if (k.toLowerCase() === "content-type") delete headers[k];
|
|
117
|
+
});
|
|
118
|
+
headers["content-type"] = ct;
|
|
119
|
+
}
|
|
120
|
+
body = yield encoded.arrayBuffer();
|
|
121
|
+
}
|
|
122
|
+
const base64Body = yield bodyToBase64(body);
|
|
123
|
+
proxyBridge.storeRequest(accessToken, requestId, method, JSON.stringify(headers), base64Body || "");
|
|
124
|
+
const proxyUrl = "/_capgo_proxy_?u=" + encodeURIComponent(url) + "&rid=" + requestId;
|
|
125
|
+
return originalFetch.call(window, proxyUrl, { method: "GET" });
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
const XHROpen = XMLHttpRequest.prototype.open;
|
|
129
|
+
const XHRSend = XMLHttpRequest.prototype.send;
|
|
130
|
+
const XHRSetHeader = XMLHttpRequest.prototype.setRequestHeader;
|
|
131
|
+
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
|
|
132
|
+
this.__proxyMethod = method;
|
|
133
|
+
this.__proxyUrl = resolveUrl(url instanceof URL ? url.toString() : url);
|
|
134
|
+
this.__proxyHeaders = {};
|
|
135
|
+
return XHROpen.apply(this, [method, url, ...rest]);
|
|
136
|
+
};
|
|
137
|
+
XMLHttpRequest.prototype.setRequestHeader = function(name, value) {
|
|
138
|
+
if (this.__proxyHeaders) {
|
|
139
|
+
this.__proxyHeaders[name] = value;
|
|
140
|
+
}
|
|
141
|
+
return XHRSetHeader.call(this, name, value);
|
|
142
|
+
};
|
|
143
|
+
XMLHttpRequest.prototype.send = function(body) {
|
|
144
|
+
const xhr = this;
|
|
145
|
+
const requestId = generateRequestId();
|
|
146
|
+
const method = xhr.__proxyMethod || "GET";
|
|
147
|
+
const url = xhr.__proxyUrl || "";
|
|
148
|
+
const headers = xhr.__proxyHeaders || {};
|
|
149
|
+
function completeSend(base64Body) {
|
|
150
|
+
proxyBridge.storeRequest(accessToken, requestId, method, JSON.stringify(headers), base64Body);
|
|
151
|
+
const proxyUrl = "/_capgo_proxy_?u=" + encodeURIComponent(url) + "&rid=" + requestId;
|
|
152
|
+
XHROpen.call(xhr, "GET", proxyUrl, true);
|
|
153
|
+
XHRSend.call(xhr, null);
|
|
154
|
+
}
|
|
155
|
+
if (body === null || body === void 0) {
|
|
156
|
+
completeSend("");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (typeof body === "string") {
|
|
160
|
+
completeSend(stringToBase64(body));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (body instanceof ArrayBuffer) {
|
|
164
|
+
completeSend(arrayBufferToBase64(body));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (ArrayBuffer.isView(body)) {
|
|
168
|
+
completeSend(arrayBufferToBase64(body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength)));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (body instanceof URLSearchParams) {
|
|
172
|
+
completeSend(stringToBase64(body.toString()));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (body instanceof Blob || body instanceof FormData) {
|
|
176
|
+
const encoded = new Response(body);
|
|
177
|
+
if (body instanceof FormData) {
|
|
178
|
+
const ct = encoded.headers.get("content-type");
|
|
179
|
+
if (ct) {
|
|
180
|
+
Object.keys(headers).forEach((k) => {
|
|
181
|
+
if (k.toLowerCase() === "content-type") delete headers[k];
|
|
182
|
+
});
|
|
183
|
+
headers["content-type"] = ct;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
encoded.arrayBuffer().then((ab) => {
|
|
187
|
+
completeSend(arrayBufferToBase64(ab));
|
|
188
|
+
}).catch((_e) => {
|
|
189
|
+
console.error("[proxy-bridge] Failed to encode Blob/FormData body:", _e);
|
|
190
|
+
completeSend("");
|
|
191
|
+
});
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
completeSend("");
|
|
195
|
+
};
|
|
196
|
+
})();
|
|
197
|
+
})();
|