cap-acadec-webview
v0.0.6
Published
Capacitor plugin to open a native WebView with cookie reading, request interception, and declarative request filtering
Maintainers
Readme
cap-acadec-webview
Capacitor plugin to open a native WebView with cookie reading, request interception, and declarative request filtering.
Opens a fullscreen native WebView (WKWebView on iOS, android.webkit.WebView on Android) as a modal on top of your app, and gives you programmatic control over what it loads.
- 🍪 Read cookies from the WebView's cookie store
- 🚦 Block or allowlist sub-resource requests with glob patterns
- ⏸️ Intercept main-frame navigations and approve/cancel them from JavaScript
- 📡 Listen to navigation state changes (URL, title, loading, canGoBack)
Install
npm install cap-acadec-webview
npx cap syncRequirements
| Platform | Minimum | | --------- | --------------------------- | | Capacitor | 7.0 – 8.x (peer dependency) | | iOS | 14.0 | | Android | minSdk 23, compileSdk 35 | | Web | fallback only (see below) |
No manual registration is needed. On Android the modal WebviewActivity is declared in the plugin's own AndroidManifest.xml and merged into your app at build time.
Usage
import { WebviewController } from 'cap-acadec-webview';
await WebviewController.open({
url: 'https://example.com/login',
headers: { 'X-App-Version': '1.2.3' },
userAgent: 'MyApp/1.2.3',
});Reading cookies
Useful for picking up a session after a third-party login flow.
const { cookies } = await WebviewController.getCookies({
url: 'https://example.com',
});
const session = cookies.find((c) => c.name === 'session_id');On iOS every cookie field is populated (
domain,path,isSecure,isHTTPOnly,expires). On Android onlynameandvalueare reliably available — the platform cookie manager does not expose the rest.
Declarative request filtering
Rules apply to sub-resource requests (images, scripts, XHR). blockPatterns is evaluated first; if allowPatterns is provided it acts as an allowlist, so everything not matching is dropped.
await WebviewController.setRequestRules({
blockPatterns: ['*://*.doubleclick.net/*', '*://*/analytics.js'],
allowPatterns: ['https://example.com/*', 'https://cdn.example.com/*'],
});Intercepting navigations
Set interceptNavigation: true and each main-frame navigation pauses until you call respondToRequest().
const handle = await WebviewController.addListener(
'requestIntercepted',
async (event) => {
const allow = new URL(event.url).hostname.endsWith('example.com');
await WebviewController.respondToRequest({
requestId: event.requestId,
allow,
});
},
);
await WebviewController.open({
url: 'https://example.com',
interceptNavigation: true,
});
// later
await handle.remove();⚠️ You must respond within 10 seconds. If you don't, the navigation is allowed by default.
Navigation state and closing
await WebviewController.addListener('navigationStateChange', (event) => {
console.log(event.url, event.title, event.isLoading, event.canGoBack);
});
await WebviewController.addListener('closed', () => {
console.log('WebView dismissed');
});
await WebviewController.close();
await WebviewController.removeAllListeners();Web fallback
The plugin ships a web implementation so your code runs in the browser during development, but it is not feature-equivalent:
| Method | Web behaviour |
| ------------------- | ----------------------------------------------------------------- |
| open() | window.open(url, '_blank'); throws if blocked by the pop-up blocker. headers, userAgent and interceptNavigation are ignored |
| close() | Closes the opened window, emits closed |
| getCookies() | Parses document.cookie — returns name/value only, and never sees HttpOnly cookies |
| setRequestRules() | No-op, logs a warning |
| respondToRequest()| No-op, logs a warning |
Guard platform-specific behaviour with Capacitor.getPlatform() when it matters.
API
open(options: OpenOptions) => Promise<void>
Open a new native WebView as a fullscreen modal.
| Option | Type | Default | Description |
| --------------------- | ------------------------ | ------- | --------------------------------------------------------------- |
| url | string | — | The URL to load. Required. |
| headers | Record<string, string> | — | HTTP headers sent with the initial request. |
| userAgent | string | — | Custom User-Agent string. |
| interceptNavigation | boolean | false | Fire requestIntercepted and wait for respondToRequest(). |
close() => Promise<void>
Close the currently open WebView.
getCookies(options?: GetCookiesOptions) => Promise<GetCookiesResult>
Read cookies from the WebView's cookie store. Pass url to scope the result to a single origin.
Returns { cookies: Cookie[] }, where Cookie is:
interface Cookie {
name: string;
value: string;
domain?: string; // iOS only
path?: string; // iOS only
isSecure?: boolean; // iOS only
isHTTPOnly?: boolean; // iOS only
expires?: string; // ISO 8601, iOS only
}setRequestRules(options: RequestRulesOptions) => Promise<void>
| Option | Type | Description |
| --------------- | ---------- | ------------------------------------------------------------------ |
| blockPatterns | string[] | Glob patterns to block. Evaluated before allowPatterns. |
| allowPatterns | string[] | Glob patterns to allow. If present, only matching URLs pass. |
respondToRequest(options: RespondToRequestOptions) => Promise<void>
| Option | Type | Description |
| ----------- | --------- | ------------------------------------------------- |
| requestId | string | The requestId from the requestIntercepted event. |
| allow | boolean | true to proceed, false to cancel. |
Events
| Event | Payload |
| ----------------------- | ------------------------------------------------------------- |
| requestIntercepted | { requestId, url, method, isMainFrame } |
| navigationStateChange | { url, title?, isLoading, canGoBack } |
| closed | void |
Use removeAllListeners() to detach every listener at once.
Development
npm install
npm run build # tsc + rollup → dist/
npm run lint # eslint + prettier --check
npm run fmt # eslint --fix + prettier --write
npm run verify # build iOS, Android, and webLicense
MIT © Acadec
