Skip to content

chore: sync upstream PR #8524 - fix(ios): remove Cordova.framework from Capacitor project#82

Open
riderx wants to merge 82 commits into
plusfrom
sync/upstream-pr-8524
Open

chore: sync upstream PR #8524 - fix(ios): remove Cordova.framework from Capacitor project#82
riderx wants to merge 82 commits into
plusfrom
sync/upstream-pr-8524

Conversation

@riderx

@riderx riderx commented Jul 7, 2026

Copy link
Copy Markdown
Member

Merge Conflict Resolution Required

The sync of upstream PR ionic-team#8524 from @jcesarmobile encountered merge conflicts.

Original PR: ionic-team#8524

What happened

  • Claude Code attempted to resolve the merge conflicts
  • This PR was created so CI and manual review can finish the sync safely

Synced from upstream by Capacitor+ Bot

Summary by CodeRabbit

  • New Features

    • Added support for loading a custom URL in the app during run.
    • Added broader Cordova plugin support on Android and iOS, including new bridge handling and package generation improvements.
    • Added a new API for reading double values from plugin configuration.
  • Bug Fixes

    • Improved system bar behavior and safe-area handling.
    • Fixed long-running CI jobs by increasing workflow timeouts.
  • Chores

    • Updated Android, iOS, CLI, and core packages to the latest alpha release and refreshed changelogs.

jworreth and others added 30 commits February 17, 2026 15:52
…m#8346)

Co-authored-by: jwo <jonathan.worreth@protonmail.ch>
Co-authored-by: Mark Anderson <mark.anderson@outsystems.com>
Co-authored-by: Steven Sherry <steven.r.sherry@gmail.com>
Co-authored-by: jcesarmobile <jcesarmobile@gmail.com>
Co-authored-by: Joseph Pender <joey.pender@outsystems.com>
jcesarmobile and others added 25 commits June 3, 2026 14:45
Co-authored-by: jcesarmobile <jcesarmobile@gmail.com>
@riderx

riderx commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Claude Code could not resolve this upstream sync completely. Please review the branch carefully before merging.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Beta npm build

Maintainers can publish one Capacitor Plus workspace package from this PR to npm for fast testing.

Comment /publish-beta <package> after the PR checks are green.

Examples:

/publish-beta core
/publish-beta cli
/publish-beta @capacitor-plus/core

If exactly one workspace package changed, /publish-beta without a package will use that package.

Packages:

  • core (@capacitor-plus/core)
  • cli (@capacitor-plus/cli)
  • android (@capacitor-plus/android)
  • ios (@capacitor-plus/ios)

The workflow will:

  • publish a prerelease package on the beta tag
  • add a pinned pr-82 dist-tag for the selected package
  • update this comment with the install command

Security note: beta publish is only enabled for branches inside this repository.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR decouples Cordova support from Capacitor core on Android and iOS into standalone CordovaPlugin implementations using a new generic call-interceptor mechanism, bumps Android/iOS SDK and toolchain versions, refactors CLI iOS Cordova podspec/SPM logic into shared utilities, replaces CLI live-reload flags with a single --url option, updates telemetry endpoints, and refreshes package metadata/changelogs for the 9.0.0-alpha.5 release.

Changes

Cordova Decoupling (Core)

Layer / File(s) Summary
Android interceptor contract and Bridge wiring
android/capacitor/src/main/java/com/getcapacitor/MessageHandler.java, Bridge.java
Adds MessageHandler.Interceptor and Bridge.getCallInterceptor/registerInterceptor, removing direct PluginManager coupling.
Bridge Cordova removal and Builder rewrite
android/capacitor/src/main/java/com/getcapacitor/Bridge.java
Removes Cordova fields/lifecycle delegation; permission, activity, and deploy checks now go through __CordovaPlugin; Builder.create() rewritten.
Android CordovaPlugin module
android/capacitor-cordova/...
New Gradle module with CordovaPlugin.java, manifest, proguard rules, and reduced visibility on mock helper classes.
iOS bridge Cordova removal
ios/Capacitor/Capacitor/CapacitorBridge.swift, CAPBridgeViewController.swift, CAPInstanceDescriptor.*, JSExport.swift, WebViewDelegationHandler.swift, CAPBridgeProtocol.swift
Removes Cordova config parsing/injection, adds RegistrationList, callInterceptors, and registerCallInterceptor.
iOS CordovaPlugin module
ios/CapacitorCordova/.../Plugin.swift, xcodeproj, podspecs
New CordovaPlugin.swift handles JS injection and "cordova" interceptor; removes legacy screen-orientation category and TmpViewController.

Estimated code review effort: 4 (Complex) | ~75 minutes

Toolchain/SDK Bumps

Layer / File(s) Summary
Android Gradle/AGP/SDK bumps
android/*, android-template/*, capacitor-cordova-android-plugins/build.gradle
Bumps AGP to 9.2.1, compileSdk/minSdk/targetSdk, and Gradle wrapper to 9.5.1 with retry config.
gradlew script rewrites
android/gradlew*, android-template/gradlew*
Removes CLASSPATH-based invocation; reworks Windows batch exit-code handling.
iOS deployment target bump
templates, podspecs, xcodeproj files, pods_helpers.rb
Raises IPHONEOS_DEPLOYMENT_TARGET to 16.0 and adopts @main entry point.

CLI Cordova/SPM and Run Command

Layer / File(s) Summary
New cordova-ios.ts utility module
cli/src/util/cordova-ios.ts
Extracts podspec/package generation, native file copying, and Podfile line generation for iOS Cordova plugins.
ios/update.ts and android/update.ts Cordova gating
cli/src/ios/update.ts, cli/src/android/update.ts
Threads enableCordova flag through update pipelines; removes Kotlin auto-detection in Android update.
SPM PackageOptions
cli/src/declarations.ts, cli/src/util/spm.ts
Adds symlink and moduleAliases support for per-plugin SPM configuration.
run --url option
cli/src/index.ts, cli/src/tasks/run.ts, cli/src/util/livereload.ts
Replaces live-reload flags with --url, validates protocol, updates config edits.
Telemetry and config updates
cli/src/ipc.ts, cli/src/telemetry.ts, cli/src/config.ts, cli/test/telemetry.spec.ts
Changes telemetry endpoint/status code, adds ios_package_manager metric, and bumps default minVersions.

Estimated code review effort: 4 (Complex) | ~60 minutes

Metadata & Release

Layer / File(s) Summary
Package metadata/versions
android/package.json, cli/package.json, core/package.json, ios/package.json, lerna.json
Renames packages to @capacitor/* and bumps to 9.0.0-alpha.5.
Changelogs
CHANGELOG.md, android/CHANGELOG.md, cli/CHANGELOG.md, core/CHANGELOG.md, ios/CHANGELOG.md
Adds new alpha release entries and updates compare links.
Migration/CI/publish scripts
cli/src/tasks/migrate.ts, .github/workflows/test.yml, scripts/publish-android.sh
Updates migration version constants, CI timeouts, and Gradle publish task names.

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant WebView
  participant Bridge
  participant CordovaPlugin
  participant PluginManager
  WebView->>Bridge: postMessage(type="cordova", data)
  Bridge->>Bridge: getCallInterceptor("cordova")
  Bridge->>CordovaPlugin: intercept(service, action, callbackId, actionArgs)
  CordovaPlugin->>PluginManager: exec(...)
  PluginManager-->>CordovaPlugin: result
  CordovaPlugin-->>WebView: callback response
Loading
sequenceDiagram
  participant CLI
  participant runCommand
  participant CapLiveReloadHelper
  participant AppConfig
  CLI->>runCommand: run --url http://host:port
  runCommand->>runCommand: validate URL protocol
  runCommand->>CapLiveReloadHelper: editCapConfigForLiveReload(config, platform, url)
  CapLiveReloadHelper->>AppConfig: write server.url to capacitor.config.json
  runCommand-->>CLI: log "listening for: url"
Loading

Related PRs: None identified in the provided context.

Suggested labels: breaking-change, cordova, android, ios, cli, release

Suggested reviewers: None specified.

🐰 Cordova hops away, a plugin now apart,
New interceptors bridge the gap with art,
SDKs climb higher, sixteen for the fold,
Nine-point-oh-alpha, a version bold,
URLs replace the reload of old.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the upstream sync and the main iOS change to remove Cordova.framework.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)

Warning

Review ran into problems

🔥 Problems

Repository analysis: Couldn't refresh Cap-go/capacitor-plus clone - clone failed: Clone operation failed: Stream initialization permanently failed: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
android/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java (1)

163-173: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Missing # delimiter corrupts URLs containing a fragment.

uri.getFragment() returns the fragment value without the leading #. Appending it directly after the query string produces a malformed URL (e.g. ...?foo=bar#section becomes ...?foo=barsection), silently corrupting any request whose URL contains a fragment.

🐛 Proposed fix
             String unEncodedUrlString =
                 uri.getScheme() +
                 "://" +
                 uri.getAuthority() +
                 uri.getPath() +
                 (!urlQuery.equals("") ? "?" + urlQuery : "") +
-                (uri.getFragment() != null ? uri.getFragment() : "");
+                (uri.getFragment() != null ? "#" + uri.getFragment() : "");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@android/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java`
around lines 163 - 173, The URL reconstruction in HttpRequestHandler is missing
the fragment delimiter, so URLs with fragments are being concatenated
incorrectly. Update the logic that builds unEncodedUrlString in the request
setup path to append the fragment from uri.getFragment() with a leading # only
when present, keeping the existing scheme, authority, path, and query handling
intact. Use the URL/URI assembly block in HttpRequestHandler to locate the fix.
android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java (1)

176-192: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Remove the API 35 gate around root insets

android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java:176-192ViewCompat.getRootWindowInsets(v) is compat-safe on older Android versions too; this branch sets the safe-area CSS vars to 0 on API 24-34 until the listener runs. Call it unconditionally here, or move the Android 15-specific check to the code that actually needs it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java`
around lines 176 - 192, The safe-area initialization in
SystemBars.initSafeAreaCSSVariables() is unnecessarily gated by the Android 15
check, which forces zero insets on older versions before listeners update.
Remove the API 35-specific branch around ViewCompat.getRootWindowInsets(v) and
fetch root window insets unconditionally here; keep any Android 15-only logic
only in the code path that truly depends on it.
CHANGELOG.md (1)

6-119: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

CHANGELOG.md was manually edited, and merge conflict resolution left duplicated/inconsistent content.

Per repo guidelines, CHANGELOG.md should not be manually edited since it's managed by CI/CD. This diff manually edits it as part of the merge sync, and the result contains clear artifacts of an unresolved conflict:

  • The 9.0.0-alpha.4 header/entry appears twice (Line 14 and Line 37).
  • The entire 9.0.0-alpha.0 "Bug Fixes" section is duplicated verbatim (Lines 26-36 and Lines 61-71).
  • Lines 111-115 mix ionic-team/capacitor compare/issue/commit URLs with Cap-go/capacitor-plus issue/commit URLs within the same entry, leaving a broken/inconsistent changelog history.

This matches the PR's own note that "Claude Code could not fully resolve the upstream sync" and should be cleaned up (or regenerated via the normal CI/CD changelog process) before merging.

As per coding guidelines, "Do not manually edit CHANGELOG.md; it is managed automatically by CI/CD."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` around lines 6 - 119, The CHANGELOG content has unresolved
merge artifacts and inconsistent history that need to be removed. Clean up the
duplicated 9.0.0-alpha.4 and 9.0.0-alpha.0 entries, then make the release notes
consistent with the upstream Capacitor history by fixing the mixed
compare/issue/commit references in the 8.3.1/8.3.2 area. Use the existing
changelog section headers and release entries as the anchor points, and ensure
the final file is either regenerated by the normal CI/CD changelog flow or left
in a single, non-duplicated, internally consistent state.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@android/capacitor/src/main/java/com/getcapacitor/Bridge.java`:
- Around line 293-308: Guard the WebView package lookup in
isMinimumWebViewInstalled() by checking the result of
WebView.getCurrentWebViewPackage() before using it, and also handle a null
versionName safely. If the package info or version string is unavailable, return
false immediately so the version parsing logic only runs when info is present.

In `@android/CHANGELOG.md`:
- Around line 6-84: The android/CHANGELOG.md release history contains duplicate
entries for several versions, which creates conflicting compare links and
repeated release notes. Remove the repeated blocks for 9.0.0-alpha.4,
9.0.0-alpha.3, 9.0.0-alpha.0, 8.4.0, 8.3.4, and 8.3.3 so each release appears
only once, keeping the correct compare link and notes in the remaining canonical
entry.

In `@cli/src/ios/update.ts`:
- Around line 65-88: The `update` flow in `cli/src/ios/update.ts` is recomputing
`getCapacitorPackageVersion` for every plugin even though `iosPlatformVersion`
is independent of `plugin`; hoist that await out of the
`Promise.all`/`validSPMPackages.map` loop and reuse the single value inside the
per-plugin work. While updating the `Package.swift` parsing logic, make sure the
`major(version)` comparison in the `regex`/`content.match` path is guarded so
malformed or missing semver values do not throw during `update`.

In `@cli/src/tasks/migrate.ts`:
- Line 3: The migration task is importing rimraf as a default export, but rimraf
v6 only exposes named exports, so the current sync call will break at runtime.
Update the import in migrate.ts to use the named sync export (for example,
rimrafSync) and change the existing rimraf.sync(...) usage in the migration
logic to call that named function instead.

In `@cli/src/util/cordova-ios.ts`:
- Around line 299-318: In cordovaPodfileLines, remove the unnecessary async from
the cordovaPlugins.map callback because it does not await anything and the logic
is synchronous. Update the loop in cordova-ios.ts so the callback used to walk
cordovaPlugins, getPlatformElement, and podspec/pods/pod stays plain synchronous
code, preserving the current pods accumulation without implying async behavior.
- Around line 340-344: generateCordovaPackageFiles is returning before the async
per-plugin work completes because the cordovaPlugins.map callback does not await
generateCordovaPackageFile. Update generateCordovaPackageFiles to wait for each
generateCordovaPackageFile call to finish, so callers like ios/update.ts do not
continue into checkPluginsForPackageSwift and generatePackageFile until all
Package.swift files are written. Use the generateCordovaPackageFiles and
generateCordovaPackageFile symbols to locate the fix.
- Around line 22-27: The async podspec writes in generateCordovaPodspecs are not
awaited, so the function can finish before the .podspec files are written and
errors may be unhandled. Update generateCordovaPodspecs in cordova-ios.ts to
await both generateCordovaPodspec calls (or run them through a Promise-based
concurrency pattern) so the plugin podspec generation completes before
installCocoaPodsPlugins continues.

In `@ios/Capacitor/Capacitor/CAPBridgeProtocol.swift`:
- Around line 82-84: The new CAPBridgeProtocol requirement
registerCallInterceptor(_:handler:) is source-breaking for existing conformers.
Update the protocol so this API is not required for all adopters, either by
moving the behavior into a protocol extension with a default implementation or
by making the interceptor registration optional in CAPBridgeProtocol while
keeping CAPBridge-related call interception functionality available.

In `@ios/Capacitor/Capacitor/CAPBridgeViewController.swift`:
- Around line 94-110: In CAPBridgeViewController.updateAppLocationIfNeeded, stop
using perform(_:) on __CordovaPlugin for cordovaDeployDisabled because it is an
`@objc` Bool and the current call can misread the scalar value. Read the property
through KVC or a typed protocol/cast on the plugin instance instead, then keep
the existing conditional logic using cordovaDeployDisabled unchanged.

In `@ios/CapacitorCordova/CapacitorCordova/Classes/Public/Plugin.swift`:
- Line 43: The cast in Plugin should use a concrete array element type instead
of the untyped Array, since `as? Array` will not compile. Update the `args`
assignment in `Plugin` to cast to `[Any]` (or the correct known element type) so
the `actionArgs` value can be read safely.

---

Outside diff comments:
In `@android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java`:
- Around line 176-192: The safe-area initialization in
SystemBars.initSafeAreaCSSVariables() is unnecessarily gated by the Android 15
check, which forces zero insets on older versions before listeners update.
Remove the API 35-specific branch around ViewCompat.getRootWindowInsets(v) and
fetch root window insets unconditionally here; keep any Android 15-only logic
only in the code path that truly depends on it.

In
`@android/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java`:
- Around line 163-173: The URL reconstruction in HttpRequestHandler is missing
the fragment delimiter, so URLs with fragments are being concatenated
incorrectly. Update the logic that builds unEncodedUrlString in the request
setup path to append the fragment from uri.getFragment() with a leading # only
when present, keeping the existing scheme, authority, path, and query handling
intact. Use the URL/URI assembly block in HttpRequestHandler to locate the fix.

In `@CHANGELOG.md`:
- Around line 6-119: The CHANGELOG content has unresolved merge artifacts and
inconsistent history that need to be removed. Clean up the duplicated
9.0.0-alpha.4 and 9.0.0-alpha.0 entries, then make the release notes consistent
with the upstream Capacitor history by fixing the mixed compare/issue/commit
references in the 8.3.1/8.3.2 area. Use the existing changelog section headers
and release entries as the anchor points, and ensure the final file is either
regenerated by the normal CI/CD changelog flow or left in a single,
non-duplicated, internally consistent state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3b6e7d24-8d64-4d89-832d-0d2cae0f09f9

📥 Commits

Reviewing files that changed from the base of the PR and between 51a1030 and 2f2895a.

⛔ Files ignored due to path filters (2)
  • android-template/gradle/wrapper/gradle-wrapper.jar is excluded by !**/*.jar
  • android/gradle/wrapper/gradle-wrapper.jar is excluded by !**/*.jar
📒 Files selected for processing (87)
  • .github/workflows/test.yml
  • CHANGELOG.md
  • android-template/app/build.gradle
  • android-template/build.gradle
  • android-template/gradle/wrapper/gradle-wrapper.properties
  • android-template/gradlew
  • android-template/gradlew.bat
  • android-template/settings.gradle
  • android-template/variables.gradle
  • android/CHANGELOG.md
  • android/capacitor-cordova/build.gradle
  • android/capacitor-cordova/proguard-rules.pro
  • android/capacitor-cordova/src/main/AndroidManifest.xml
  • android/capacitor-cordova/src/main/java/com/getcapacitor/cordova/CapacitorCordovaCookieManager.java
  • android/capacitor-cordova/src/main/java/com/getcapacitor/cordova/CordovaPlugin.java
  • android/capacitor-cordova/src/main/java/com/getcapacitor/cordova/MockCordovaInterfaceImpl.java
  • android/capacitor-cordova/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java
  • android/capacitor/build.gradle
  • android/capacitor/proguard-rules.pro
  • android/capacitor/src/main/java/com/getcapacitor/Bridge.java
  • android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java
  • android/capacitor/src/main/java/com/getcapacitor/FileUtils.java
  • android/capacitor/src/main/java/com/getcapacitor/MessageHandler.java
  • android/capacitor/src/main/java/com/getcapacitor/PluginConfig.java
  • android/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java
  • android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookieManager.java
  • android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java
  • android/capacitor/src/main/java/com/getcapacitor/plugin/util/CapacitorHttpUrlConnection.java
  • android/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java
  • android/capacitor/src/main/java/com/getcapacitor/util/JSONUtils.java
  • android/capacitor/src/test/java/com/getcapacitor/plugin/SystemBarsTest.java
  • android/gradle/wrapper/gradle-wrapper.properties
  • android/gradlew
  • android/gradlew.bat
  • android/package.json
  • android/settings.gradle
  • capacitor-cordova-android-plugins/build.gradle
  • cli/CHANGELOG.md
  • cli/package.json
  • cli/src/android/update.ts
  • cli/src/config.ts
  • cli/src/declarations.ts
  • cli/src/index.ts
  • cli/src/ios/update.ts
  • cli/src/ipc.ts
  • cli/src/tasks/migrate.ts
  • cli/src/tasks/run.ts
  • cli/src/telemetry.ts
  • cli/src/util/cordova-ios.ts
  • cli/src/util/iosplugin.ts
  • cli/src/util/livereload.ts
  • cli/src/util/spm.ts
  • cli/test/telemetry.spec.ts
  • core/CHANGELOG.md
  • core/package.json
  • ios-pods-template/App/App.xcodeproj/project.pbxproj
  • ios-pods-template/App/App/AppDelegate.swift
  • ios-pods-template/App/Podfile
  • ios-spm-template/App/App.xcodeproj/project.pbxproj
  • ios-spm-template/App/App/AppDelegate.swift
  • ios-spm-template/App/CapApp-SPM/Package.swift
  • ios/CHANGELOG.md
  • ios/Capacitor.podspec
  • ios/Capacitor/Capacitor.xcodeproj/project.pbxproj
  • ios/Capacitor/Capacitor/CAPApplicationDelegateProxy.swift
  • ios/Capacitor/Capacitor/CAPBridgeProtocol.swift
  • ios/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.h
  • ios/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.m
  • ios/Capacitor/Capacitor/CAPBridgeViewController.swift
  • ios/Capacitor/Capacitor/CAPInstanceDescriptor.h
  • ios/Capacitor/Capacitor/CAPInstanceDescriptor.m
  • ios/Capacitor/Capacitor/CAPInstanceDescriptor.swift
  • ios/Capacitor/Capacitor/CapacitorBridge.swift
  • ios/Capacitor/Capacitor/JS.swift
  • ios/Capacitor/Capacitor/JSExport.swift
  • ios/Capacitor/Capacitor/PluginConfig.swift
  • ios/Capacitor/Capacitor/TmpViewController.swift
  • ios/Capacitor/Capacitor/WebViewDelegationHandler.swift
  • ios/Capacitor/CapacitorTests/ConfigurationTests.swift
  • ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m
  • ios/CapacitorCordova.podspec
  • ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.pbxproj
  • ios/CapacitorCordova/CapacitorCordova/Classes/Public/Plugin.swift
  • ios/package.json
  • ios/scripts/pods_helpers.rb
  • lerna.json
  • scripts/publish-android.sh
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)
💤 Files with no reviewable changes (10)
  • ios/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.h
  • ios/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.m
  • ios/Capacitor/Capacitor/JSExport.swift
  • android-template/settings.gradle
  • ios/Capacitor/Capacitor/CAPInstanceDescriptor.m
  • android-template/app/build.gradle
  • ios/Capacitor/CapacitorTests/ConfigurationTests.swift
  • ios/Capacitor/Capacitor/TmpViewController.swift
  • ios/Capacitor/Capacitor/CAPApplicationDelegateProxy.swift
  • android/capacitor/proguard-rules.pro

Comment on lines 293 to 308
@SuppressLint("WebViewApiAvailability")
public boolean isMinimumWebViewInstalled() {
PackageManager pm = getContext().getPackageManager();

// Check getCurrentWebViewPackage() directly if above Android 8
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PackageInfo info = WebView.getCurrentWebViewPackage();
Pattern pattern = Pattern.compile("(\\d+)");
Matcher matcher = pattern.matcher(info.versionName);
if (matcher.find()) {
String majorVersionStr = matcher.group(0);
int majorVersion = Integer.parseInt(majorVersionStr);
if (info.packageName.equals("com.huawei.webview")) {
return majorVersion >= config.getMinHuaweiWebViewVersion();
}
return majorVersion >= config.getMinWebViewVersion();
} else {
return false;
}
}

// Otherwise manually check WebView versions
try {
PackageInfo info = InternalUtils.getPackageInfo(pm, "com.android.chrome");
String majorVersionStr = info.versionName.split("\\.")[0];
int majorVersion = Integer.parseInt(majorVersionStr);
return majorVersion >= config.getMinWebViewVersion();
} catch (Exception ex) {
Logger.warn("Unable to get package info for 'com.google.android.webview'" + ex.toString());
}

try {
PackageInfo info = InternalUtils.getPackageInfo(pm, "com.android.webview");
String majorVersionStr = info.versionName.split("\\.")[0];
PackageInfo info = WebView.getCurrentWebViewPackage();
Pattern pattern = Pattern.compile("(\\d+)");
Matcher matcher = pattern.matcher(info.versionName);
if (matcher.find()) {
String majorVersionStr = matcher.group(0);
int majorVersion = Integer.parseInt(majorVersionStr);
if (info.packageName.equals("com.huawei.webview")) {
return majorVersion >= config.getMinHuaweiWebViewVersion();
}
return majorVersion >= config.getMinWebViewVersion();
} catch (Exception ex) {
Logger.warn("Unable to get package info for 'com.android.webview'" + ex.toString());
}

final int amazonFireMajorWebViewVersion = extractWebViewMajorVersion(pm, "com.amazon.webview.chromium");
if (amazonFireMajorWebViewVersion >= config.getMinWebViewVersion()) {
return true;
}

// Could not detect any webview, return false
return false;
}

private int extractWebViewMajorVersion(final PackageManager pm, final String webViewPackageName) {
try {
final PackageInfo info = InternalUtils.getPackageInfo(pm, webViewPackageName);
final String majorVersionStr = info.versionName.split("\\.")[0];
final int majorVersion = Integer.parseInt(majorVersionStr);
return majorVersion;
} catch (Exception ex) {
Logger.warn(String.format("Unable to get package info for '%s' with err '%s'", webViewPackageName, ex));
} else {
return false;
}
return 0;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target method and nearby constructor/load flow.
sed -n '250,340p' android/capacitor/src/main/java/com/getcapacitor/Bridge.java

printf '\n--- constructor/load flow ---\n'
sed -n '170,230p' android/capacitor/src/main/java/com/getcapacitor/Bridge.java

printf '\n--- search for current WebView package usage ---\n'
rg -n "getCurrentWebViewPackage|versionName|isMinimumWebViewInstalled" android/capacitor/src/main/java -S

printf '\n--- search for previous implementation or related guards ---\n'
git diff -- android/capacitor/src/main/java/com/getcapacitor/Bridge.java | sed -n '1,220p'

Repository: Cap-go/capacitor-plus

Length of output: 1955


🏁 Script executed (no clone):

#!/bin/bash
set -euo pipefail

# Query Android documentation for nullability of WebView.getCurrentWebViewPackage()
python3 - <<'PY'
import urllib.request, urllib.parse, re
queries = [
    "Android WebView.getCurrentWebViewPackage nullable PackageInfo versionName null",
]
for q in queries:
    url = "https://www.google.com/search?q=" + urllib.parse.quote(q)
    print("QUERY:", q)
    try:
        with urllib.request.urlopen(url, timeout=10) as r:
            html = r.read().decode("utf-8", "ignore")
        # very light extraction
        for m in re.finditer(r"getCurrentWebViewPackage|PackageInfo|versionName|nullable", html, re.I):
            start = max(0, m.start()-120)
            end = min(len(html), m.end()+160)
            print(html[start:end].replace("\n", " ")[:280])
            print("---")
            break
    except Exception as e:
        print("ERR:", e)
PY

Length of output: 146


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for any existing null handling or assumptions around WebView package info.
rg -n "WebView\.getCurrentWebViewPackage|PackageInfo info = WebView|getMinHuaweiWebViewVersion|getMinWebViewVersion" android -S

# Show the exact method with line numbers.
nl -ba android/capacitor/src/main/java/com/getcapacitor/Bridge.java | sed -n '292,312p'

Repository: Cap-go/capacitor-plus

Length of output: 1955


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check the Android minSdk to see whether the WebView API call needs a version gate.
rg -n "minSdkVersion|minSdk" android -S

# Inspect the manifest / gradle file locations likely to define it.
fd -a "build.gradle*" android
fd -a "gradle.properties" android
fd -a "AndroidManifest.xml" android/capacitor/src/main

Repository: Cap-go/capacitor-plus

Length of output: 1955


Guard the WebView package lookup. WebView.getCurrentWebViewPackage() and info.versionName can be null here, which will crash before the fallback runs. Return false when package info isn’t available.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@android/capacitor/src/main/java/com/getcapacitor/Bridge.java` around lines
293 - 308, Guard the WebView package lookup in isMinimumWebViewInstalled() by
checking the result of WebView.getCurrentWebViewPackage() before using it, and
also handle a null versionName safely. If the package info or version string is
unavailable, return false immediately so the version parsing logic only runs
when info is present.

Comment thread android/CHANGELOG.md
Comment on lines +6 to +84
# [9.0.0-alpha.5](https://github.com/ionic-team/capacitor/compare/8.4.1...9.0.0-alpha.5) (2026-06-23)

### Bug Fixes

* address follow-up review comments ([8bee786](https://github.com/Cap-go/capacitor-plus/commit/8bee786e2c68ca6c351e88f104b518291c1f81e3))
* **android:** Add missing null checks in BridgeActivity ([#8185](https://github.com/Cap-go/capacitor-plus/issues/8185)) ([bd29b99](https://github.com/Cap-go/capacitor-plus/commit/bd29b9913a9279de26fc21c6cb0b93b8f5e5433a))
* **android:** AGP 9.0 no longer supports `proguard-android.txt` ([#8315](https://github.com/Cap-go/capacitor-plus/issues/8315)) ([dcc76c3](https://github.com/Cap-go/capacitor-plus/commit/dcc76c37508a9b71fb36d95707748c2dd115cf52))
* **android:** Concurrent Range Requests for assets ([#8357](https://github.com/Cap-go/capacitor-plus/issues/8357)) ([5e82c89](https://github.com/Cap-go/capacitor-plus/commit/5e82c89f1bff6d0e9ccea2554007aacb920d4c58))
* **android:** correctly parsing `server.url` when they include paths ([#8391](https://github.com/Cap-go/capacitor-plus/issues/8391)) ([a9f2181](https://github.com/Cap-go/capacitor-plus/commit/a9f218179b60555d86b44bf2b33354da3e64e98c))
* **android:** handle lowercase range header ([#8368](https://github.com/Cap-go/capacitor-plus/issues/8368)) ([ae0e2dd](https://github.com/Cap-go/capacitor-plus/commit/ae0e2ddccb2904ee4b3d47d4be1f7556ac7000a1))
* **android:** handle null versionName in isNewBinary() ([#8397](https://github.com/Cap-go/capacitor-plus/issues/8397)) ([aa1a660](https://github.com/Cap-go/capacitor-plus/commit/aa1a660f364f9b5f5a1e350e279c8864b04dd13b))
* **android:** invalid http range seeking ([#8369](https://github.com/Cap-go/capacitor-plus/issues/8369)) ([3109d22](https://github.com/Cap-go/capacitor-plus/commit/3109d22547253ed44293777c60652f14cf83e416))
* boundary value extraction for form-data requests ([#7518](https://github.com/Cap-go/capacitor-plus/issues/7518)) ([64ab854](https://github.com/Cap-go/capacitor-plus/commit/64ab854c12330804c24275d88d3a9f7c8e52a73d))
* **http:** handle URL objects on fetch ([#8386](https://github.com/Cap-go/capacitor-plus/issues/8386)) ([003099a](https://github.com/Cap-go/capacitor-plus/commit/003099aef246adfd76d890074d46b1484951824b))
* resolve upstream sync conflicts ([75cbb30](https://github.com/Cap-go/capacitor-plus/commit/75cbb3097a7068bcb37313cbe6301628079101ca))
* **system-bars:** use separate current styles ([#8409](https://github.com/Cap-go/capacitor-plus/issues/8409)) ([3d1f8d1](https://github.com/Cap-go/capacitor-plus/commit/3d1f8d1b61480187375f5cd4de7ba999db007542))
* **SystemBars:** avoid extra view padding on API <= 34 ([#8439](https://github.com/Cap-go/capacitor-plus/issues/8439)) ([5b135a7](https://github.com/Cap-go/capacitor-plus/commit/5b135a70217be560e7176c8d5b514cc92ed3e4e4))
* **SystemBars:** get correct style on handleOnConfigurationChanged ([#8295](https://github.com/Cap-go/capacitor-plus/issues/8295)) ([2a66b44](https://github.com/Cap-go/capacitor-plus/commit/2a66b44915895f971e4a26a8612798aa2f95ea11))
* **SystemBars:** Set window background color according to theme ([#8306](https://github.com/Cap-go/capacitor-plus/issues/8306)) ([6037e38](https://github.com/Cap-go/capacitor-plus/commit/6037e3836ec24c9ddf26e74e5fbec20ab506adfd))
* **SystemBars:** Skipping margin manipulation when on a fixed WebView ([#8309](https://github.com/Cap-go/capacitor-plus/issues/8309)) ([53c33b6](https://github.com/Cap-go/capacitor-plus/commit/53c33b614218bf635322fbdf9a38038a7964e3d4))
* **SystemBars:** use native safe area insets on Android ([#8384](https://github.com/Cap-go/capacitor-plus/issues/8384)) ([4e99598](https://github.com/Cap-go/capacitor-plus/commit/4e99598a2a57ee97e82be1aaa09492744622fa60))


### Reverts

* revert version bump from [#8319](https://github.com/Cap-go/capacitor-plus/issues/8319) and [#8320](https://github.com/Cap-go/capacitor-plus/issues/8320) ([a48ebb6](https://github.com/Cap-go/capacitor-plus/commit/a48ebb622ea4ebe92927bf1756a4d8ac6012884b))
- **android:** restore verify script ([#8513](https://github.com/ionic-team/capacitor/issues/8513)) ([0585c18](https://github.com/ionic-team/capacitor/commit/0585c180843064d4f704f38710bd0db5050b70b1))

# [9.0.0-alpha.4](https://github.com/ionic-team/capacitor/compare/9.0.0-alpha.3...9.0.0-alpha.4) (2026-06-19)

# [9.0.0-alpha.3](https://github.com/ionic-team/capacitor/compare/8.4.0...9.0.0-alpha.3) (2026-06-02)

# [9.0.0-alpha.2](https://github.com/ionic-team/capacitor/compare/8.3.4...9.0.0-alpha.2) (2026-05-12)

# [9.0.0-alpha.1](https://github.com/ionic-team/capacitor/compare/8.3.3...9.0.0-alpha.1) (2026-05-08)

## [8.0.8](https://github.com/Cap-go/capacitor-plus/compare/8.0.7...8.0.8) (2026-04-08)

# [9.0.0-alpha.0](https://github.com/ionic-team/capacitor/compare/8.3.2...9.0.0-alpha.0) (2026-05-07)

### Bug Fixes

* **android:** use proguard-android-optimize for AGP 9 compatibility ([52ceef3](https://github.com/Cap-go/capacitor-plus/commit/52ceef3769544c6cb0cbc83963dcc4552983578b))




- **android:** conditionally add Cordova ([#8453](https://github.com/ionic-team/capacitor/issues/8453)) ([e136b3f](https://github.com/ionic-team/capacitor/commit/e136b3f0cdd1437cac5234576301ed388edf85e7))
- **android:** Handle activity result without plugin handle ([#8436](https://github.com/ionic-team/capacitor/issues/8436)) ([65ad1fd](https://github.com/ionic-team/capacitor/commit/65ad1fd55b9793a3e078e4a837a00e2f28c75c17))
- **http:** handle URL objects on fetch ([#8386](https://github.com/ionic-team/capacitor/issues/8386)) ([0aac1f0](https://github.com/ionic-team/capacitor/commit/0aac1f0aee8083dc5013f0d8e3c180eb02f21141))
- **SystemBars:** use native safe area insets on Android ([#8384](https://github.com/ionic-team/capacitor/issues/8384)) ([d55f4f8](https://github.com/ionic-team/capacitor/commit/d55f4f859bd88fa5617699e874c48c451bcb5e5f))

## [8.0.7](https://github.com/Cap-go/capacitor-plus/compare/8.0.6...8.0.7) (2026-01-12)
# [9.0.0-alpha.4](https://github.com/ionic-team/capacitor/compare/9.0.0-alpha.3...9.0.0-alpha.4) (2026-06-19)

**Note:** Version bump only for package @capacitor-plus/android
## [8.4.1](https://github.com/ionic-team/capacitor/compare/8.4.0...8.4.1) (2026-06-19)

# [8.4.0](https://github.com/ionic-team/capacitor/compare/9.0.0-alpha.2...8.4.0) (2026-06-02)

**Note:** Version bump only for package @capacitor/android

# [9.0.0-alpha.3](https://github.com/ionic-team/capacitor/compare/9.0.0-alpha.2...9.0.0-alpha.3) (2026-06-02)

# [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02)

## [8.0.6](https://github.com/Cap-go/capacitor-plus/compare/8.0.5...8.0.6) (2026-01-09)

**Note:** Version bump only for package @capacitor-plus/android





## [8.0.5](https://github.com/Cap-go/capacitor-plus/compare/8.0.4...8.0.5) (2026-01-08)

**Note:** Version bump only for package @capacitor-plus/android


### Bug Fixes

- **android:** show only the requested system bar ([#8480](https://github.com/ionic-team/capacitor/issues/8480)) ([4c6c321](https://github.com/ionic-team/capacitor/commit/4c6c3219afb5223211e857457e46283c37eb9424))
- **SystemBars:** make `safe-area-inset-x` available on API <= 34 ([#8424](https://github.com/ionic-team/capacitor/issues/8424)) ([e456de0](https://github.com/ionic-team/capacitor/commit/e456de083e19644f484bec5a5359cb67960ac8bc))
- **SystemBars:** respect `insetsHandling` disable ([#8481](https://github.com/ionic-team/capacitor/issues/8481)) ([d4ad7ff](https://github.com/ionic-team/capacitor/commit/d4ad7ffe39daf66e0cfc63af9028d5c05543bde7))

### Features

## [8.0.4](https://github.com/Cap-go/capacitor-plus/compare/8.0.3...8.0.4) (2025-12-16)
- add method getDouble to plugin config ([#7638](https://github.com/ionic-team/capacitor/issues/7638)) ([93c72de](https://github.com/ionic-team/capacitor/commit/93c72de40a2ec4c78b33659250cb08340083088e))

**Note:** Version bump only for package @capacitor-plus/android
## [8.3.4](https://github.com/ionic-team/capacitor/compare/9.0.0-alpha.1...8.3.4) (2026-05-12)

## [8.3.3](https://github.com/ionic-team/capacitor/compare/9.0.0-alpha.0...8.3.3) (2026-05-08)

# [9.0.0-alpha.2](https://github.com/ionic-team/capacitor/compare/9.0.0-alpha.1...9.0.0-alpha.2) (2026-05-12)

**Note:** Version bump only for package @capacitor/android

# [9.0.0-alpha.1](https://github.com/ionic-team/capacitor/compare/9.0.0-alpha.0...9.0.0-alpha.1) (2026-05-08)

## [8.0.3](https://github.com/Cap-go/capacitor-plus/compare/8.0.2...8.0.3) (2025-12-16)
**Note:** Version bump only for package @capacitor/android

# [9.0.0-alpha.0](https://github.com/ionic-team/capacitor/compare/8.3.2...9.0.0-alpha.0) (2026-05-07)

### Bug Fixes

* update homepage URL in package.json files for all platforms ([61ccdc4](https://github.com/Cap-go/capacitor-plus/commit/61ccdc4128a1ce2a7178eb0a195b188876ec0a9d))



- **android:** conditionally add Cordova ([#8453](https://github.com/ionic-team/capacitor/issues/8453)) ([e136b3f](https://github.com/ionic-team/capacitor/commit/e136b3f0cdd1437cac5234576301ed388edf85e7))
- **android:** Handle activity result without plugin handle ([#8436](https://github.com/ionic-team/capacitor/issues/8436)) ([65ad1fd](https://github.com/ionic-team/capacitor/commit/65ad1fd55b9793a3e078e4a837a00e2f28c75c17))
- **http:** handle URL objects on fetch ([#8386](https://github.com/ionic-team/capacitor/issues/8386)) ([0aac1f0](https://github.com/ionic-team/capacitor/commit/0aac1f0aee8083dc5013f0d8e3c180eb02f21141))
- **SystemBars:** use native safe area insets on Android ([#8384](https://github.com/ionic-team/capacitor/issues/8384)) ([d55f4f8](https://github.com/ionic-team/capacitor/commit/d55f4f859bd88fa5617699e874c48c451bcb5e5f))

## [8.3.4](https://github.com/ionic-team/capacitor/compare/8.3.3...8.3.4) (2026-05-12)

## [8.0.2](https://github.com/Cap-go/capacitor-plus/compare/8.0.1...8.0.2) (2025-12-16)
**Note:** Version bump only for package @capacitor/android

## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08)

### Features
**Note:** Version bump only for package @capacitor/android

* add new workflows for testing and version bumping; update README files for all packages ([a01c2a8](https://github.com/Cap-go/capacitor-plus/commit/a01c2a842c363c2aa58e5681210fa62fac8e5de5))





## [8.0.1](https://github.com/Cap-go/capacitor-plus/compare/3.3.4...8.0.1) (2025-12-16)

### Bug Fixes

- 204 http response ([#6266](https://github.com/Cap-go/capacitor-plus/issues/6266)) ([771f6ce](https://github.com/Cap-go/capacitor-plus/commit/771f6ce1f35159848db218a42dc4f56b5106f750))
- add http method to prototype.open ([#6740](https://github.com/Cap-go/capacitor-plus/issues/6740)) ([1fd2d87](https://github.com/Cap-go/capacitor-plus/commit/1fd2d8762ff2341a8fe20eec9e774c6a29576e88))
- allow single parameter on setRequestBody ([#6728](https://github.com/Cap-go/capacitor-plus/issues/6728)) ([5343bdb](https://github.com/Cap-go/capacitor-plus/commit/5343bdb60d26849cd8f9c8ff28ba7d9ddbd05b26))
- **android:** add EdgeToEdge compatibility ([#7871](https://github.com/Cap-go/capacitor-plus/issues/7871)) ([64a8bc4](https://github.com/Cap-go/capacitor-plus/commit/64a8bc40de2522c75a94a40cba6c8ccd82481cb8))
- **android:** added ServerPath object and building options for setting initial load from portals ([#6008](https://github.com/Cap-go/capacitor-plus/issues/6008)) ([205b6e6](https://github.com/Cap-go/capacitor-plus/commit/205b6e61806158244846608b1e6c0c7b26ee4ab7))
- **android:** allow single input file selection from samsumg gallery ([#6778](https://github.com/Cap-go/capacitor-plus/issues/6778)) ([3d57ecd](https://github.com/Cap-go/capacitor-plus/commit/3d57ecdf7631d1581047bd5d9f86ea657ecad845))
- **android:** Allow WebView to load blob urls ([#7551](https://github.com/Cap-go/capacitor-plus/issues/7551)) ([0dca917](https://github.com/Cap-go/capacitor-plus/commit/0dca917da54b01c6cf4fcd063f8191a8457d7c93))
- **android:** Allow WebView to load data urls ([#6418](https://github.com/Cap-go/capacitor-plus/issues/6418)) ([daf2ec6](https://github.com/Cap-go/capacitor-plus/commit/daf2ec64df0c567c6a42560488e5d2515eff8a33))
- **android:** avoid crash if server url ends in / ([#7426](https://github.com/Cap-go/capacitor-plus/issues/7426)) ([f8264cc](https://github.com/Cap-go/capacitor-plus/commit/f8264ccae1f2fec553521bc62d767c4909ea6d79))
- **android:** avoid R8 optimizations remove plugin classes ([#6783](https://github.com/Cap-go/capacitor-plus/issues/6783)) ([cc85df5](https://github.com/Cap-go/capacitor-plus/commit/cc85df5f3a6999883623054573bafc30665e41e7))
- **android:** better cleaning of allowedOrigin url ([#7607](https://github.com/Cap-go/capacitor-plus/issues/7607)) ([d123260](https://github.com/Cap-go/capacitor-plus/commit/d123260c70f26b0e786515ced9c95447f9ee81a0))
- **android:** consider display cutout area for insets ([#8042](https://github.com/Cap-go/capacitor-plus/issues/8042)) ([b478211](https://github.com/Cap-go/capacitor-plus/commit/b4782116856c35e3fb567393f10a36ce4632b44c))
- **android:** don't proxy requests if no jsInjector ([#7199](https://github.com/Cap-go/capacitor-plus/issues/7199)) ([7dc5585](https://github.com/Cap-go/capacitor-plus/commit/7dc5585996c17eedd154b5d9118eb880fef616fe))
- **android:** Don't run Cordova plugins on ui thread ([#6108](https://github.com/Cap-go/capacitor-plus/issues/6108)) ([592ee86](https://github.com/Cap-go/capacitor-plus/commit/592ee862a58f5cb0737620a0246fe8ae295d27cf))
- **android:** get application/x-www-form-urlencoded as string ([#6165](https://github.com/Cap-go/capacitor-plus/issues/6165)) ([0735e89](https://github.com/Cap-go/capacitor-plus/commit/0735e89d48e77a1ddca97a48e3851f4a0a3ea2c1))
- **android:** handle deprecation warnings ([#7190](https://github.com/Cap-go/capacitor-plus/issues/7190)) ([06636d7](https://github.com/Cap-go/capacitor-plus/commit/06636d73a1b12c8f932642ee7caf91432690fea5))
- **android:** handle empty permission list ([#6375](https://github.com/Cap-go/capacitor-plus/issues/6375)) ([b11a9df](https://github.com/Cap-go/capacitor-plus/commit/b11a9df070f18a25364a9109e295556fc75ea7f9))
- **android:** handle http errors on the proxy ([#7280](https://github.com/Cap-go/capacitor-plus/issues/7280)) ([cca3c80](https://github.com/Cap-go/capacitor-plus/commit/cca3c80298b768a5eaf1da4d95f659e303ed7042))
- **android:** handle null http headers and params ([#6370](https://github.com/Cap-go/capacitor-plus/issues/6370)) ([e486672](https://github.com/Cap-go/capacitor-plus/commit/e486672731818d5c64c50956562aa4766f169d41))
- **android:** handle webview version for developer builds ([#6907](https://github.com/Cap-go/capacitor-plus/issues/6907)) ([88498e6](https://github.com/Cap-go/capacitor-plus/commit/88498e6228492a9ae917d3a7b37c242881f9fe52))
- **android:** incorrect http url params encoding ([#6586](https://github.com/Cap-go/capacitor-plus/issues/6586)) ([e9ddb0c](https://github.com/Cap-go/capacitor-plus/commit/e9ddb0cfdb1ed320b650e1d01a04d37e644f6dd3))
- **android:** javascript injection not working on urls with query ([#7545](https://github.com/Cap-go/capacitor-plus/issues/7545)) ([57ce5c6](https://github.com/Cap-go/capacitor-plus/commit/57ce5c65560c34d106e8b88cffe26ad22947bba6))
- **android:** launching intents without host ([#6489](https://github.com/Cap-go/capacitor-plus/issues/6489)) ([95f7474](https://github.com/Cap-go/capacitor-plus/commit/95f747401ac5a666de4338a18666060e9c1ff39e))
- **android:** let WebView handle errors ([#7286](https://github.com/Cap-go/capacitor-plus/issues/7286)) ([286b694](https://github.com/Cap-go/capacitor-plus/commit/286b69460f1227a75a9865f91fb51c455fd4370e))
- **android:** make JSInjector replace first <head> only ([#6895](https://github.com/Cap-go/capacitor-plus/issues/6895)) ([93c8a8d](https://github.com/Cap-go/capacitor-plus/commit/93c8a8ddbc547a6a9501e02a73719268228ebdca))
- **android:** make local urls use unpatched fetch ([#6953](https://github.com/Cap-go/capacitor-plus/issues/6953)) ([e50e56c](https://github.com/Cap-go/capacitor-plus/commit/e50e56c5231f230497d1bd420e02e2e065c38f86))
- **android:** make removeAllListeners return a promise ([#5527](https://github.com/Cap-go/capacitor-plus/issues/5527)) ([6f4d858](https://github.com/Cap-go/capacitor-plus/commit/6f4d858ea879d97109c0c7da2d664d04806adc2a))
- **android:** Move bridge localUrl initialization to initWebView ([#6685](https://github.com/Cap-go/capacitor-plus/issues/6685)) ([7f5f0ca](https://github.com/Cap-go/capacitor-plus/commit/7f5f0ca4220d40d6a19c778c18f9534ef3b65899))
- **android:** move initialFocus on webview into config ([#5579](https://github.com/Cap-go/capacitor-plus/issues/5579)) ([8b4e861](https://github.com/Cap-go/capacitor-plus/commit/8b4e861514b0fbe08e9296f49c280234f54742e1))
- **android:** open external links in browser ([#5913](https://github.com/Cap-go/capacitor-plus/issues/5913)) ([7553ede](https://github.com/Cap-go/capacitor-plus/commit/7553ede93170971e21ab3dec1798443d084ead2a))
- **android:** prevent app from loading if server.url is invalid ([d4a0dea](https://github.com/Cap-go/capacitor-plus/commit/d4a0deaa37eda4476f0be030e266c2c1260fc6e8))
- **android:** prevent crash on script injection if the script is too long ([#7308](https://github.com/Cap-go/capacitor-plus/issues/7308)) ([c9895e8](https://github.com/Cap-go/capacitor-plus/commit/c9895e89aeb69613906fc8a2270f7bf3f4913fda))
- **android:** prevent input file crash if accept has . ([#5363](https://github.com/Cap-go/capacitor-plus/issues/5363)) ([bdacb30](https://github.com/Cap-go/capacitor-plus/commit/bdacb300bb6391dc4b84bb2bab075df993a15cba))
- **android:** proper app url check for launching intents ([#6450](https://github.com/Cap-go/capacitor-plus/issues/6450)) ([302ba35](https://github.com/Cap-go/capacitor-plus/commit/302ba353acbd6d67e96e2b28870bc9c5bb4e9af0))
- **android:** Publish proguard-rules.pro on npm ([#5761](https://github.com/Cap-go/capacitor-plus/issues/5761)) ([df77103](https://github.com/Cap-go/capacitor-plus/commit/df77103ca411fa452239099769289eeeea2404d2))
- **android:** Remove calculated bottom inset if keyboard is visible ([#8280](https://github.com/Cap-go/capacitor-plus/issues/8280)) ([196b642](https://github.com/Cap-go/capacitor-plus/commit/196b642236d293a5012e3c307fcd942766e56cce))
- **android:** remove kotlin-bom dependency ([#8237](https://github.com/Cap-go/capacitor-plus/issues/8237)) ([a894749](https://github.com/Cap-go/capacitor-plus/commit/a89474920569d404e3b19e22e782e656d5b59bdd))
- **android:** Remove path from allowedOriginRules ([#7293](https://github.com/Cap-go/capacitor-plus/issues/7293)) ([9eb565c](https://github.com/Cap-go/capacitor-plus/commit/9eb565cddd30888125d1503d1c0a5aa5aa5e48cb))
- **android:** remove stored references to bridge that holds it in memory ([#6448](https://github.com/Cap-go/capacitor-plus/issues/6448)) ([4737d2b](https://github.com/Cap-go/capacitor-plus/commit/4737d2b46b480c7c0246ac6414494cbbdac7811b))
- **android:** rename bridge layout to avoid collision ([#7919](https://github.com/Cap-go/capacitor-plus/issues/7919)) ([a629f16](https://github.com/Cap-go/capacitor-plus/commit/a629f167b345cda1c44f37131235d14353eff504))
- **android:** replace deprecated Gradle property name syntax ([b68ac9e](https://github.com/Cap-go/capacitor-plus/commit/b68ac9e2dfc3ed292b7879bd7aeaab3d05ac84d5))
- **android:** revert cookie manager initialization to plugin load ([53a2d47](https://github.com/Cap-go/capacitor-plus/commit/53a2d4792e026a89723a672a01fc34990add71f0))
- **android:** sanitize portable file name ([#7894](https://github.com/Cap-go/capacitor-plus/issues/7894)) ([5f09297](https://github.com/Cap-go/capacitor-plus/commit/5f092970e33da1ec896efc4e2a5ae3fb77fca658))
- **android:** send FormData on older devices ([#7519](https://github.com/Cap-go/capacitor-plus/issues/7519)) ([de8b50d](https://github.com/Cap-go/capacitor-plus/commit/de8b50dc1d87510c5f19d04f30b6be12b51d8482))
- **android:** set all cookies on proxied requests ([#5781](https://github.com/Cap-go/capacitor-plus/issues/5781)) ([5ef6a38](https://github.com/Cap-go/capacitor-plus/commit/5ef6a3889121dd39a9159ff80250df18854bc557))
- **android:** set WebViewClient on the WebView ([#5919](https://github.com/Cap-go/capacitor-plus/issues/5919)) ([020ed8e](https://github.com/Cap-go/capacitor-plus/commit/020ed8eaeb7864399d4b93f54ab7601c607d8e0d))
- **android:** Silence deprecation warning on handlePermissionResult ([#6092](https://github.com/Cap-go/capacitor-plus/issues/6092)) ([888b13e](https://github.com/Cap-go/capacitor-plus/commit/888b13e89c48dab949b38135a3ec443ac4fd852e))
- **android:** solve and/or silence lint errors ([#6358](https://github.com/Cap-go/capacitor-plus/issues/6358)) ([c627415](https://github.com/Cap-go/capacitor-plus/commit/c627415743bec92dcb65ab8b8840003d8c0a5286))
- **android:** unify kotlin dependency version ([#6501](https://github.com/Cap-go/capacitor-plus/issues/6501)) ([0a40477](https://github.com/Cap-go/capacitor-plus/commit/0a4047768cbde9bc17d92955e64ab11d2e3b3335))
- **android:** Use Logger class instead of Log in CapacitorCookieManager ([#6923](https://github.com/Cap-go/capacitor-plus/issues/6923)) ([8aaa356](https://github.com/Cap-go/capacitor-plus/commit/8aaa356ab1f14b56df821e8ac0bb7e43bfa094fa))
- **android:** UTF-8 encode form data value ([#7525](https://github.com/Cap-go/capacitor-plus/issues/7525)) ([a73ed31](https://github.com/Cap-go/capacitor-plus/commit/a73ed318cdb819863425f6b1b7ec23ea53454931))
- **cookies:** check isEnabled before setting cookieHandler ([bb04f24](https://github.com/Cap-go/capacitor-plus/commit/bb04f24f0b4a99e46ed5ca047d3d3df81804d516))
- **cookies:** hide httpOnly cookies from client ([0cc927e](https://github.com/Cap-go/capacitor-plus/commit/0cc927ef5f0f7076a6d486d666d78483f1d71c54))
- **cookies:** init cookie manager after server url is set ([0ee772f](https://github.com/Cap-go/capacitor-plus/commit/0ee772ff6456ad0948a0dd025dfcf2658a5563a0))
- **cookies:** make document.cookie setter synchronous ([2272abf](https://github.com/Cap-go/capacitor-plus/commit/2272abf3d3d9dc82d9ca0d03b17e2b78f11f61fc))
- **cookies:** remove session cookies when initializing the cookie manager ([037863b](https://github.com/Cap-go/capacitor-plus/commit/037863bea6f3a00978125dc2f8ecba1e896c0740))
- **cookies:** sanitize url before retrieving/setting cookies ([ca40634](https://github.com/Cap-go/capacitor-plus/commit/ca4063471f215d3f7525e51592d9c72138a52855))
- **cookies:** Use Set-Cookie headers to persist cookies ([57f8b39](https://github.com/Cap-go/capacitor-plus/commit/57f8b39d7f4c5ee0e5e5cb316913e9450a81d22b))
- **core:** Exception object was not set on Cap ([#5917](https://github.com/Cap-go/capacitor-plus/issues/5917)) ([9ca27a4](https://github.com/Cap-go/capacitor-plus/commit/9ca27a4f8441b368f8bf9d97dda57b1a55ac0e4e))
- **core:** make 'content-type' header count for XMLHttpRequest patch ([#7161](https://github.com/Cap-go/capacitor-plus/issues/7161)) ([26d7f68](https://github.com/Cap-go/capacitor-plus/commit/26d7f688284914c6ef795564ba424119efc32a1c))
- handle fetch headers that are Headers objects ([#6320](https://github.com/Cap-go/capacitor-plus/issues/6320)) ([cb00e49](https://github.com/Cap-go/capacitor-plus/commit/cb00e4952acca8e877555f30b2190f6685d25934))
- http content headers not sent when using axios ([#8039](https://github.com/Cap-go/capacitor-plus/issues/8039)) ([67cac40](https://github.com/Cap-go/capacitor-plus/commit/67cac40660b3e8cc78d1d228b7c6915450948ef1))
- **http:** add support for Request objects in fetch ([24b3cc1](https://github.com/Cap-go/capacitor-plus/commit/24b3cc113e3d8aae5d85dbf2d25bec0c35136477))
- **http:** Add URLSearchParams support ([#7374](https://github.com/Cap-go/capacitor-plus/issues/7374)) ([9367ecc](https://github.com/Cap-go/capacitor-plus/commit/9367ecc56a0c78249dccdf95dca5006422144289))
- **http:** better handling of active requests and shutting down gracefully ([5d294c9](https://github.com/Cap-go/capacitor-plus/commit/5d294c9b84f09bab649a7112c86959a41a9a4f5e))
- **http:** boundary not added for Request objects ([#7897](https://github.com/Cap-go/capacitor-plus/issues/7897)) ([bdaa6f3](https://github.com/Cap-go/capacitor-plus/commit/bdaa6f3c38c33f3a021ac61f2de89101a5b66cff))
- **http:** change proxy url generation ([#7354](https://github.com/Cap-go/capacitor-plus/issues/7354)) ([318c316](https://github.com/Cap-go/capacitor-plus/commit/318c316847c5b059fb88b46d4acd31e1ced477e5))
- **http:** disconnect active connections if call or bridge is destroyed ([a1ed6cc](https://github.com/Cap-go/capacitor-plus/commit/a1ed6cc6f07465d683b95e3796d944f863a7b857))
- **http:** don't override readyState for non POST requests ([#7488](https://github.com/Cap-go/capacitor-plus/issues/7488)) ([30c13a8](https://github.com/Cap-go/capacitor-plus/commit/30c13a865e7710e6dc5f0ee014e951d52d030795))
- **http:** don't throw errors when content-type is null on response ([#6627](https://github.com/Cap-go/capacitor-plus/issues/6627)) ([538821f](https://github.com/Cap-go/capacitor-plus/commit/538821f267aa3b79548fed6aaea8880ff949ffdd))
- **http:** fire events in correct order when using xhr ([5ed3617](https://github.com/Cap-go/capacitor-plus/commit/5ed361787596bb5949f6ae5e366495f296352bf3))
- **http:** fix exception thrown on 204 responses ([1f6e8be](https://github.com/Cap-go/capacitor-plus/commit/1f6e8be9d8813c4397e2c54ac4c06beb55f97b5f))
- **http:** fix local http requests on native platforms ([c4e040a](https://github.com/Cap-go/capacitor-plus/commit/c4e040a6f8c6b54bac6ae320e5f0f008604fe50f))
- **http:** handle proxy urls with port ([#7273](https://github.com/Cap-go/capacitor-plus/issues/7273)) ([514409a](https://github.com/Cap-go/capacitor-plus/commit/514409aeb93ad65be105bbe2da8d2cd86ff159b0))
- **http:** handle UInt8Array on body ([#7546](https://github.com/Cap-go/capacitor-plus/issues/7546)) ([cfb9ce1](https://github.com/Cap-go/capacitor-plus/commit/cfb9ce175615f69fe86b61af6d51ec2044d147cd))
- **http:** inherit object properties on window.XMLHttpRequest ([91c11d0](https://github.com/Cap-go/capacitor-plus/commit/91c11d06f773c45a10f6f2d52f672ae6f189b162))
- **http:** keep original URL properties on proxy ([#7329](https://github.com/Cap-go/capacitor-plus/issues/7329)) ([cbb6407](https://github.com/Cap-go/capacitor-plus/commit/cbb6407225b42a0d9db4f335a9766f119501021d))
- **http:** Make proxy work with Request objects ([#7348](https://github.com/Cap-go/capacitor-plus/issues/7348)) ([7e68725](https://github.com/Cap-go/capacitor-plus/commit/7e6872573df03ab5cdc10a1a27db3e9fe81a141d))
- **http:** parse readablestream data on fetch request objects ([#6919](https://github.com/Cap-go/capacitor-plus/issues/6919)) ([80ec3b7](https://github.com/Cap-go/capacitor-plus/commit/80ec3b73db18b7b6841bf90ed50a67389946ab87))
- **http:** pass original url as query param on the proxy url ([#7527](https://github.com/Cap-go/capacitor-plus/issues/7527)) ([1da06e6](https://github.com/Cap-go/capacitor-plus/commit/1da06e66cb9cfbf5a5cc48ba6c23cdbe18bc8fc0))
- **http:** prevent POST request from being proxied ([#7395](https://github.com/Cap-go/capacitor-plus/issues/7395)) ([7b8c352](https://github.com/Cap-go/capacitor-plus/commit/7b8c3523decd5610dcf09e926640bf35b382d61d))
- **http:** Properly URL-encode key and values during `x-www-form-urlencoded` POSTs ([#8037](https://github.com/Cap-go/capacitor-plus/issues/8037)) ([87b4641](https://github.com/Cap-go/capacitor-plus/commit/87b4641d1fa32b78e6fc2e87ee7b2c49b625b213))
- **http:** properly write form-urlencoded data on android request body ([#7001](https://github.com/Cap-go/capacitor-plus/issues/7001)) ([a986ee5](https://github.com/Cap-go/capacitor-plus/commit/a986ee541f54a1d3ac637b514fe547b224b36903))
- **http:** return numbers and booleans as-is when application/json is the content type ([03dd3f9](https://github.com/Cap-go/capacitor-plus/commit/03dd3f96c7ee75b6fff2b7c40d0c9a58fb04fce5))
- **http:** return valid response for relative url xhr requests ([bde6569](https://github.com/Cap-go/capacitor-plus/commit/bde65696218f97a8328041f137457f46e5eb766a))
- **http:** route get requests through custom handler ([#6818](https://github.com/Cap-go/capacitor-plus/issues/6818)) ([b853d06](https://github.com/Cap-go/capacitor-plus/commit/b853d065055b5a819949551be58b62d40b52e37c))
- **http:** set port for proxy url ([#7341](https://github.com/Cap-go/capacitor-plus/issues/7341)) ([a3059dc](https://github.com/Cap-go/capacitor-plus/commit/a3059dca4a7746d9fb7102a7d41f4da80e2f48b4))
- **ios/android:** better http error handling ([#6208](https://github.com/Cap-go/capacitor-plus/issues/6208)) ([7d4d70a](https://github.com/Cap-go/capacitor-plus/commit/7d4d70a0500b7996c710c0762907f44bdf27c92b))
- **ios/android:** copy url from nativeResponse to response ([#6482](https://github.com/Cap-go/capacitor-plus/issues/6482)) ([828fb71](https://github.com/Cap-go/capacitor-plus/commit/828fb71ebb52c0655d5879ad0edaac7368ab2b96))
- **ios:** Correctly Attach Headers to Request ([#6303](https://github.com/Cap-go/capacitor-plus/issues/6303)) ([a3f875c](https://github.com/Cap-go/capacitor-plus/commit/a3f875cf42e111fde07d6e87643264b19ed77573))
- **ios:** crash when http headers contain numbers ([#6251](https://github.com/Cap-go/capacitor-plus/issues/6251)) ([028c556](https://github.com/Cap-go/capacitor-plus/commit/028c556a50b41ee99fe8f4f1aa2f42d3fd57f92d))
- make Plugin.resolve act consistently ([#8225](https://github.com/Cap-go/capacitor-plus/issues/8225)) ([06aeb9e](https://github.com/Cap-go/capacitor-plus/commit/06aeb9e85d162d6be9d96820edcb2008cd74da84))
- remove accept-charset ([#6386](https://github.com/Cap-go/capacitor-plus/issues/6386)) ([bbf6f7e](https://github.com/Cap-go/capacitor-plus/commit/bbf6f7e1af0c49c0bc917942b6715c613be3f557))
- Remove all plugin listeners in bridge reset ([#7962](https://github.com/Cap-go/capacitor-plus/issues/7962)) ([06aeea9](https://github.com/Cap-go/capacitor-plus/commit/06aeea973aa56ac2fb791f893ebd899253ee65f9))
- secure cookies often are not set by the cookie plugin ([#7261](https://github.com/Cap-go/capacitor-plus/issues/7261)) ([cda1886](https://github.com/Cap-go/capacitor-plus/commit/cda18861aea3ced7835f959cba612cea98761c58))
- vue 3 log warning causes error on iOS ([#6993](https://github.com/Cap-go/capacitor-plus/issues/6993)) ([87271e2](https://github.com/Cap-go/capacitor-plus/commit/87271e2671013ad35d13b22f2e96d4fe8f4eeaf0))
## [8.3.2](https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2) (2026-05-07)

### Features
### Bug Fixes

- Add function to inject external JS into WebView before document load ([#7864](https://github.com/Cap-go/capacitor-plus/issues/7864)) ([ec0954c](https://github.com/Cap-go/capacitor-plus/commit/ec0954c197543e913939f3ab9c4bcb172bfa3530))
- Add global initialFocus configuration ([#7775](https://github.com/Cap-go/capacitor-plus/issues/7775)) ([61d0165](https://github.com/Cap-go/capacitor-plus/commit/61d01653685d8e3594d2d8a6bd870fa9643ba95c))
- Add option for custom error page ([#5723](https://github.com/Cap-go/capacitor-plus/issues/5723)) ([e8bdef3](https://github.com/Cap-go/capacitor-plus/commit/e8bdef3b4634e4ad45fa8fc34c7c0ab8dfa383f3))
- **android:** don't allow server.androidScheme to be set to schemes handled by WebView ([01285ba](https://github.com/Cap-go/capacitor-plus/commit/01285ba253d602b08a41240ad2ccf370730d51a3))
- **android/cli:** Allow to use the old addJavascriptInterface bridge ([#6043](https://github.com/Cap-go/capacitor-plus/issues/6043)) ([a6e7c54](https://github.com/Cap-go/capacitor-plus/commit/a6e7c5422687b703492a5fcc49369eacc376143d))
- **android:** add ability to create config from a custom file path ([#6264](https://github.com/Cap-go/capacitor-plus/issues/6264)) ([42b4f0f](https://github.com/Cap-go/capacitor-plus/commit/42b4f0f416c8038ae368860007910bb09c8ec84e))
- **android:** add adjustMarginsForEdgeToEdge configuration option ([#7885](https://github.com/Cap-go/capacitor-plus/issues/7885)) ([1ea86d1](https://github.com/Cap-go/capacitor-plus/commit/1ea86d166afd315e72847c5e734a8c175fb90e04))
- **android:** Add android.minWebviewVersion configuration option ([#5768](https://github.com/Cap-go/capacitor-plus/issues/5768)) ([ad83827](https://github.com/Cap-go/capacitor-plus/commit/ad838279e9cd190ce6f1a020a0ac9e3916786324))
- **android:** add check for excluded domains before ssl request ([7906d36](https://github.com/Cap-go/capacitor-plus/commit/7906d3616e8bfb2e2c1c81ee123424c06fc4e5ab))
- **android:** Add getLong helper on PluginCall ([#5235](https://github.com/Cap-go/capacitor-plus/issues/5235)) ([26261fb](https://github.com/Cap-go/capacitor-plus/commit/26261fb49211330c4db72c259359565da7d7bc4b))
- **android:** Add Optional Data Param for Error Object ([#5719](https://github.com/Cap-go/capacitor-plus/issues/5719)) ([174172b](https://github.com/Cap-go/capacitor-plus/commit/174172b6c64dc9117c48ed0e20c25e0b6c2fb625))
- **android:** Add overridable routing for WebViewLocalServer ([#5553](https://github.com/Cap-go/capacitor-plus/issues/5553)) ([3bb288e](https://github.com/Cap-go/capacitor-plus/commit/3bb288e848c5c0e49c1e58c0782e0b1ffd7b1f31))
- **android:** Add SSL Pinning logic ([#6314](https://github.com/Cap-go/capacitor-plus/issues/6314)) ([07f113e](https://github.com/Cap-go/capacitor-plus/commit/07f113e6933e15c45d772f69f7128cbb3706f7b9))
- **android:** allow developers to provide logic for onRenderProcessGone in WebViewListener ([#6966](https://github.com/Cap-go/capacitor-plus/issues/6966)) ([79e17bb](https://github.com/Cap-go/capacitor-plus/commit/79e17bb5e6ccd813bddc626703152d3983f6d93b))
- **android:** Bump default minSdkVersion to 24 ([#8083](https://github.com/Cap-go/capacitor-plus/issues/8083)) ([c022ddf](https://github.com/Cap-go/capacitor-plus/commit/c022ddf21452379bb183ff7c846f73bd07a15dbf))
- **android:** enable loading of assets outside of the content web asset directory ([#6301](https://github.com/Cap-go/capacitor-plus/issues/6301)) ([364497d](https://github.com/Cap-go/capacitor-plus/commit/364497d4aca93fc716a0673ef9103479aed791ec))
- **android:** Fix for [#6258](https://github.com/Cap-go/capacitor-plus/issues/6258), Add support for modern Huawei devices ([#6402](https://github.com/Cap-go/capacitor-plus/issues/6402)) ([17f2f4a](https://github.com/Cap-go/capacitor-plus/commit/17f2f4ac744a038c1dae3cbd74a670d5ede92ef3))
- **android:** Improving SystemBars inset handling ([#8268](https://github.com/Cap-go/capacitor-plus/issues/8268)) ([81ae30a](https://github.com/Cap-go/capacitor-plus/commit/81ae30a503797e417dd125b06262dabc4696c88a))
- **android:** Load alternative layout when no WebView ([#7141](https://github.com/Cap-go/capacitor-plus/issues/7141)) ([87c399a](https://github.com/Cap-go/capacitor-plus/commit/87c399ab6b41f217b4d8a58bfb916a5d78641fd0))
- **android:** Plugin Instance Support ([#6073](https://github.com/Cap-go/capacitor-plus/issues/6073)) ([3d5b7c2](https://github.com/Cap-go/capacitor-plus/commit/3d5b7c2d372cf764c625f46d1e8761e05b8959da))
- **android:** Removing enableJetifier ([#6333](https://github.com/Cap-go/capacitor-plus/issues/6333)) ([fc0b403](https://github.com/Cap-go/capacitor-plus/commit/fc0b403265f63eab35cdb2f262fb1e047db4b6bd))
- **android:** set default targetSDK to 31 ([#5442](https://github.com/Cap-go/capacitor-plus/issues/5442)) ([4442459](https://github.com/Cap-go/capacitor-plus/commit/4442459b24cdbac25cb1e4de11583d22c21452b3))
- **android:** set default targetSDK to 32 ([#5611](https://github.com/Cap-go/capacitor-plus/issues/5611)) ([416b966](https://github.com/Cap-go/capacitor-plus/commit/416b9662fbf6233d23216c0c0441862603c3a723))
- **android:** update gradle to 8.0.2 and gradle plugin to 8.0.0 ([#6497](https://github.com/Cap-go/capacitor-plus/issues/6497)) ([01b5b39](https://github.com/Cap-go/capacitor-plus/commit/01b5b399324ae5d0896989478a6910fb946542d7))
- **android:** update support for Portals for Capacitor to include Live Updates ([#5660](https://github.com/Cap-go/capacitor-plus/issues/5660)) ([62f0a5e](https://github.com/Cap-go/capacitor-plus/commit/62f0a5eaa40776aad79dbf8f8c0900037d3cc97e))
- **android:** Upgrade gradle to 7.4 ([#5445](https://github.com/Cap-go/capacitor-plus/issues/5445)) ([28eaf18](https://github.com/Cap-go/capacitor-plus/commit/28eaf1851fa7a912917dbb40c68fb4dd583d08ad))
- **android:** Use addWebMessageListener where available ([#5427](https://github.com/Cap-go/capacitor-plus/issues/5427)) ([c2dfe80](https://github.com/Cap-go/capacitor-plus/commit/c2dfe808446717412b35e82713d123b7a052f264))
- **android:** Use java 11 ([#5552](https://github.com/Cap-go/capacitor-plus/issues/5552)) ([e47959f](https://github.com/Cap-go/capacitor-plus/commit/e47959fcbd6a89b97b1275a5814fdb4e7ce30672))
- Capacitor Cookies & Capacitor Http core plugins ([d4047cf](https://github.com/Cap-go/capacitor-plus/commit/d4047cfa947676777f400389a8d65defae140b45))
- **cookies:** add get cookies plugin method ([ba1e770](https://github.com/Cap-go/capacitor-plus/commit/ba1e7702a3338714aee24388c0afea39706c9341))
- expose `appStartPath` on cap config server configuration ([#8019](https://github.com/Cap-go/capacitor-plus/issues/8019)) ([a274fef](https://github.com/Cap-go/capacitor-plus/commit/a274fef069176a8e528a22f4734d1e29a539709c))
- **http:** Apply overrideUserAgent to requests ([#7906](https://github.com/Cap-go/capacitor-plus/issues/7906)) ([52482c9](https://github.com/Cap-go/capacitor-plus/commit/52482c9d3c575b737054b41f9d1730c70cc5f471))
- **http:** support for FormData requests ([#6708](https://github.com/Cap-go/capacitor-plus/issues/6708)) ([849c564](https://github.com/Cap-go/capacitor-plus/commit/849c56458205bea3b078b1ee19807d7fd84c47b1))
- Implement automated upstream sync and review process for Capacitor+ ([54a5dfb](https://github.com/Cap-go/capacitor-plus/commit/54a5dfbd1f81ca4144e13b3051bf592d3aaf1f4a))
- **iOS, Android:** add AppUUID Lib for plugins ([#5690](https://github.com/Cap-go/capacitor-plus/issues/5690)) ([05e76cf](https://github.com/Cap-go/capacitor-plus/commit/05e76cf526a44e07fa75f9482fa2223a13918638))
- retain multiple calls per event until consumed ([#6419](https://github.com/Cap-go/capacitor-plus/issues/6419)) ([5aba2cb](https://github.com/Cap-go/capacitor-plus/commit/5aba2cbe29bdbab2a7af861c65d8323acf9c54a6))
- support for Amazon Fire WebView ([#6603](https://github.com/Cap-go/capacitor-plus/issues/6603)) ([3cb4eb8](https://github.com/Cap-go/capacitor-plus/commit/3cb4eb89632bce8dc872418fdb130bfd4de40b68))
- System Bars Plugin ([#8180](https://github.com/Cap-go/capacitor-plus/issues/8180)) ([a32216a](https://github.com/Cap-go/capacitor-plus/commit/a32216ac0607172a3a9c7ae5cdbfc598769294a6))
- **webview:** add setServerAssetPath method ([881235b](https://github.com/Cap-go/capacitor-plus/commit/881235b14de23ef988746bfb89a5a0fc3c8d8466))
- **SystemBars:** avoid extra view padding on API <= 34 ([#8439](https://github.com/ionic-team/capacitor/issues/8439)) ([5b135a7](https://github.com/ionic-team/capacitor/commit/5b135a70217be560e7176c8d5b514cc92ed3e4e4))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file list =="
git ls-files android/CHANGELOG.md

echo
echo "== numbered excerpt =="
sed -n '1,130p' android/CHANGELOG.md | cat -n

echo
echo "== duplicate heading candidates =="
python3 - <<'PY'
from pathlib import Path
import re
text = Path("android/CHANGELOG.md").read_text()
headings = []
for i, line in enumerate(text.splitlines(), 1):
    m = re.match(r'^(#{1,6})\s+\[([^\]]+)\]\(([^)]+)\)\s+\(([^)]+)\)\s*$', line)
    if m:
        headings.append((i, m.group(2), m.group(3), m.group(4), line))
from collections import defaultdict
by_ver = defaultdict(list)
for item in headings:
    by_ver[item[1]].append(item)
for ver, items in by_ver.items():
    if len(items) > 1:
        print(f"VERSION {ver}")
        for i, ver, url, date, line in items:
            print(f"  line {i}: {line}")
PY

Repository: Cap-go/capacitor-plus

Length of output: 1955


Remove the duplicated release entries in android/CHANGELOG.md. 9.0.0-alpha.4, 9.0.0-alpha.3, 9.0.0-alpha.0, 8.4.0, 8.3.4, and 8.3.3 each appear twice, with conflicting compare links in several cases. The changelog should have one entry per release to avoid contradictory release history.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@android/CHANGELOG.md` around lines 6 - 84, The android/CHANGELOG.md release
history contains duplicate entries for several versions, which creates
conflicting compare links and repeated release notes. Remove the repeated blocks
for 9.0.0-alpha.4, 9.0.0-alpha.3, 9.0.0-alpha.0, 8.4.0, 8.3.4, and 8.3.3 so each
release appears only once, keeping the correct compare link and notes in the
remaining canonical entry.

Comment thread cli/src/ios/update.ts
Comment on lines +65 to +88
await Promise.all(
validSPMPackages.map(async (plugin) => {
const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name);
const packageSwiftPath = join(plugin.rootPath, 'Package.swift');
let content = await readFile(packageSwiftPath, { encoding: 'utf-8' });
const regex = new RegExp(
'url:\\s*"https://github.com/ionic-team/capacitor-swift-pm\\.git",\\s*from:\\s*"([^"]+)"',
);
const version = content.match(regex)?.[1];
const majorCapVersion = major(iosPlatformVersion);
if (version && major(version) != majorCapVersion) {
const preCapVersion = prerelease(iosPlatformVersion);
const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`;
content = setAllStringIn(
content,
`url: "https://github.com/ionic-team/capacitor-swift-pm.git",`,
`)`,
` from: "${forceVersion}"`,
);
await writeFile(packageSwiftPath, content);
logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`);
}
}),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Hoist getCapacitorPackageVersion out of the per-plugin loop.

iosPlatformVersion does not depend on plugin, yet it is awaited once per package inside the Promise.all map. Compute it once before the loop. Also note major(version) will throw if the regex-captured version is not valid semver; consider guarding if plugin Package.swift contents can be malformed.

♻️ Proposed change
     const validSPMPackages = await checkPluginsForPackageSwift(config, plugins);
+    const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name);
     await Promise.all(
       validSPMPackages.map(async (plugin) => {
-        const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name);
         const packageSwiftPath = join(plugin.rootPath, 'Package.swift');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await Promise.all(
validSPMPackages.map(async (plugin) => {
const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name);
const packageSwiftPath = join(plugin.rootPath, 'Package.swift');
let content = await readFile(packageSwiftPath, { encoding: 'utf-8' });
const regex = new RegExp(
'url:\\s*"https://github.com/ionic-team/capacitor-swift-pm\\.git",\\s*from:\\s*"([^"]+)"',
);
const version = content.match(regex)?.[1];
const majorCapVersion = major(iosPlatformVersion);
if (version && major(version) != majorCapVersion) {
const preCapVersion = prerelease(iosPlatformVersion);
const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`;
content = setAllStringIn(
content,
`url: "https://github.com/ionic-team/capacitor-swift-pm.git",`,
`)`,
` from: "${forceVersion}"`,
);
await writeFile(packageSwiftPath, content);
logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`);
}
}),
);
const validSPMPackages = await checkPluginsForPackageSwift(config, plugins);
const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name);
await Promise.all(
validSPMPackages.map(async (plugin) => {
const packageSwiftPath = join(plugin.rootPath, 'Package.swift');
let content = await readFile(packageSwiftPath, { encoding: 'utf-8' });
const regex = new RegExp(
'url:\\s*"https://github.com/ionic-team/capacitor-swift-pm\\.git",\\s*from:\\s*"([^"]+)"',
);
const version = content.match(regex)?.[1];
const majorCapVersion = major(iosPlatformVersion);
if (version && major(version) != majorCapVersion) {
const preCapVersion = prerelease(iosPlatformVersion);
const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`;
content = setAllStringIn(
content,
`url: "https://github.com/ionic-team/capacitor-swift-pm.git",`,
`)`,
` from: "${forceVersion}"`,
);
await writeFile(packageSwiftPath, content);
logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`);
}
}),
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/ios/update.ts` around lines 65 - 88, The `update` flow in
`cli/src/ios/update.ts` is recomputing `getCapacitorPackageVersion` for every
plugin even though `iosPlatformVersion` is independent of `plugin`; hoist that
await out of the `Promise.all`/`validSPMPackages.map` loop and reuse the single
value inside the per-plugin work. While updating the `Package.swift` parsing
logic, make sure the `major(version)` comparison in the `regex`/`content.match`
path is guarded so malformed or missing semver values do not throw during
`update`.

Comment thread cli/src/tasks/migrate.ts
import { writeFileSync, readFileSync, existsSync } from 'fs-extra';
import { join } from 'path';
import { rimraf } from 'rimraf';
import rimraf from 'rimraf';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package version references =="
rg -n '"rimraf"|rimraf@|from '\''rimraf'\''|from \"rimraf\"' cli package.json pnpm-lock.yaml package-lock.json yarn.lock --no-messages || true

echo
echo "== migrate.ts context =="
sed -n '1,380p' cli/src/tasks/migrate.ts

Repository: Cap-go/capacitor-plus

Length of output: 1955


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate rimraf package metadata if present =="
fd -a "package.json" . | rg "rimraf|cli/package.json|package.json$" || true

echo
echo "== search for rimraf usages =="
rg -n "\brimraf\b" . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' || true

echo
echo "== inspect relevant package file(s) =="
for f in cli/package.json package.json pnpm-lock.yaml package-lock.json yarn.lock; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    sed -n '1,260p' "$f"
  fi
done

Repository: Cap-go/capacitor-plus

Length of output: 1955


🌐 Web query:

rimraf v6 default export named exports rimrafSync sync import documentation

💡 Result:

In rimraf v6, there is no default export [1][2]. You must use named imports to access the library's functions [1][3]. To use the synchronous version of rimraf, import rimrafSync from the package [1][2]: import { rimrafSync } from 'rimraf'; You can also import other available functions, such as the primary async rimraf function or native implementations, using the same named export pattern [3][2]: import { rimraf, rimrafSync, native, nativeSync } from 'rimraf'; If you are using CommonJS, use destructuring assignment to access these named exports [3][2]: const { rimraf, rimrafSync } = require('rimraf');

Citations:


🌐 Web query:

site:npmjs.com rimraf 6.0.1 exports rimrafSync default export

💡 Result:

In rimraf version 6.0.1 and later, there is no default export [1]. You must import the functions directly using named imports [1]. For example, to use rimrafSync, you should use the following syntax: import { rimrafSync } from 'rimraf'; [1] Alternatively, if you are using CommonJS, you can import the functions from the package as follows: const { rimrafSync } = require('rimraf');

Citations:


Switch to the named rimraf export. rimraf v6 has no default export, so rimraf.sync(...) will fail at runtime; import rimrafSync and call that instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/tasks/migrate.ts` at line 3, The migration task is importing rimraf
as a default export, but rimraf v6 only exposes named exports, so the current
sync call will break at runtime. Update the import in migrate.ts to use the
named sync export (for example, rimrafSync) and change the existing
rimraf.sync(...) usage in the migration logic to call that named function
instead.

Comment on lines +22 to +27
export async function generateCordovaPodspecs(cordovaPlugins: Plugin[], config: Config): Promise<void> {
const staticPlugins = cordovaPlugins.filter((p) => needsStaticPod(p));
const noStaticPlugins = cordovaPlugins.filter((el) => !staticPlugins.includes(el));
generateCordovaPodspec(noStaticPlugins, config, false);
generateCordovaPodspec(staticPlugins, config, true);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Await the async podspec generation calls.

generateCordovaPodspec is async and performs writeFile, but both invocations are fire-and-forget. generateCordovaPodspecs resolves before the .podspec files are actually written, so the downstream pod install in installCocoaPodsPlugins can race against unfinished writes (and any write error becomes an unhandled rejection).

🐛 Proposed fix
 export async function generateCordovaPodspecs(cordovaPlugins: Plugin[], config: Config): Promise<void> {
   const staticPlugins = cordovaPlugins.filter((p) => needsStaticPod(p));
   const noStaticPlugins = cordovaPlugins.filter((el) => !staticPlugins.includes(el));
-  generateCordovaPodspec(noStaticPlugins, config, false);
-  generateCordovaPodspec(staticPlugins, config, true);
+  await Promise.all([
+    generateCordovaPodspec(noStaticPlugins, config, false),
+    generateCordovaPodspec(staticPlugins, config, true),
+  ]);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function generateCordovaPodspecs(cordovaPlugins: Plugin[], config: Config): Promise<void> {
const staticPlugins = cordovaPlugins.filter((p) => needsStaticPod(p));
const noStaticPlugins = cordovaPlugins.filter((el) => !staticPlugins.includes(el));
generateCordovaPodspec(noStaticPlugins, config, false);
generateCordovaPodspec(staticPlugins, config, true);
}
export async function generateCordovaPodspecs(cordovaPlugins: Plugin[], config: Config): Promise<void> {
const staticPlugins = cordovaPlugins.filter((p) => needsStaticPod(p));
const noStaticPlugins = cordovaPlugins.filter((el) => !staticPlugins.includes(el));
await Promise.all([
generateCordovaPodspec(noStaticPlugins, config, false),
generateCordovaPodspec(staticPlugins, config, true),
]);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/util/cordova-ios.ts` around lines 22 - 27, The async podspec writes
in generateCordovaPodspecs are not awaited, so the function can finish before
the .podspec files are written and errors may be unhandled. Update
generateCordovaPodspecs in cordova-ios.ts to await both generateCordovaPodspec
calls (or run them through a Promise-based concurrency pattern) so the plugin
podspec generation completes before installCocoaPodsPlugins continues.

Comment on lines +299 to +318
cordovaPlugins.map(async (p) => {
const podspecs = getPlatformElement(p, platform, 'podspec');
podspecs.map((podspec: any) => {
podspec.pods.map((pPods: any) => {
pPods.pod.map((pod: any) => {
if (pod.$.git) {
let gitRef = '';
if (pod.$.tag) {
gitRef = `, :tag => '${pod.$.tag}'`;
} else if (pod.$.branch) {
gitRef = `, :branch => '${pod.$.branch}'`;
} else if (pod.$.commit) {
gitRef = `, :commit => '${pod.$.commit}'`;
}
pods.push(` pod '${pod.$.name}', :git => '${pod.$.git}'${gitRef}\n`);
}
});
});
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the unnecessary async callback in cordovaPodfileLines.

The .map(async (p) => {...}) body contains no await, so it currently runs synchronously and pods is populated before the function returns. But marking it async is misleading and will silently break the synchronous pods accumulation if anyone later adds an await inside. Since this function is synchronous, use a plain callback.

♻️ Proposed change
-  cordovaPlugins.map(async (p) => {
+  cordovaPlugins.map((p) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cordovaPlugins.map(async (p) => {
const podspecs = getPlatformElement(p, platform, 'podspec');
podspecs.map((podspec: any) => {
podspec.pods.map((pPods: any) => {
pPods.pod.map((pod: any) => {
if (pod.$.git) {
let gitRef = '';
if (pod.$.tag) {
gitRef = `, :tag => '${pod.$.tag}'`;
} else if (pod.$.branch) {
gitRef = `, :branch => '${pod.$.branch}'`;
} else if (pod.$.commit) {
gitRef = `, :commit => '${pod.$.commit}'`;
}
pods.push(` pod '${pod.$.name}', :git => '${pod.$.git}'${gitRef}\n`);
}
});
});
});
});
cordovaPlugins.map((p) => {
const podspecs = getPlatformElement(p, platform, 'podspec');
podspecs.map((podspec: any) => {
podspec.pods.map((pPods: any) => {
pPods.pod.map((pod: any) => {
if (pod.$.git) {
let gitRef = '';
if (pod.$.tag) {
gitRef = `, :tag => '${pod.$.tag}'`;
} else if (pod.$.branch) {
gitRef = `, :branch => '${pod.$.branch}'`;
} else if (pod.$.commit) {
gitRef = `, :commit => '${pod.$.commit}'`;
}
pods.push(` pod '${pod.$.name}', :git => '${pod.$.git}'${gitRef}\n`);
}
});
});
});
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/util/cordova-ios.ts` around lines 299 - 318, In cordovaPodfileLines,
remove the unnecessary async from the cordovaPlugins.map callback because it
does not await anything and the logic is synchronous. Update the loop in
cordova-ios.ts so the callback used to walk cordovaPlugins, getPlatformElement,
and podspec/pods/pod stays plain synchronous code, preserving the current pods
accumulation without implying async behavior.

Comment on lines +340 to +344
export async function generateCordovaPackageFiles(cordovaPlugins: Plugin[], config: Config): Promise<void> {
cordovaPlugins.map((plugin: any) => {
generateCordovaPackageFile(plugin, config);
});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Await per-plugin package file generation.

generateCordovaPackageFile is async and writes Package.swift, but the .map callbacks are never awaited, so generateCordovaPackageFiles resolves before any file is written. The caller in ios/update.ts (Line 61) proceeds to checkPluginsForPackageSwift/generatePackageFile, which can observe missing or partially written files.

🐛 Proposed fix
 export async function generateCordovaPackageFiles(cordovaPlugins: Plugin[], config: Config): Promise<void> {
-  cordovaPlugins.map((plugin: any) => {
-    generateCordovaPackageFile(plugin, config);
-  });
+  await Promise.all(cordovaPlugins.map((plugin: Plugin) => generateCordovaPackageFile(plugin, config)));
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function generateCordovaPackageFiles(cordovaPlugins: Plugin[], config: Config): Promise<void> {
cordovaPlugins.map((plugin: any) => {
generateCordovaPackageFile(plugin, config);
});
}
export async function generateCordovaPackageFiles(cordovaPlugins: Plugin[], config: Config): Promise<void> {
await Promise.all(cordovaPlugins.map((plugin: Plugin) => generateCordovaPackageFile(plugin, config)));
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/util/cordova-ios.ts` around lines 340 - 344,
generateCordovaPackageFiles is returning before the async per-plugin work
completes because the cordovaPlugins.map callback does not await
generateCordovaPackageFile. Update generateCordovaPackageFiles to wait for each
generateCordovaPackageFile call to finish, so callers like ios/update.ts do not
continue into checkPluginsForPackageSwift and generatePackageFile until all
Package.swift files are written. Use the generateCordovaPackageFiles and
generateCordovaPackageFile symbols to locate the fix.

Comment on lines +82 to +84
// MARK: - Interceptors
func registerCallInterceptor(_ name: String, handler: @escaping ([String: Any]) -> Void)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== CAPBridgeProtocol.swift ==\n'
sed -n '1,180p' ios/Capacitor/Capacitor/CAPBridgeProtocol.swift

printf '\n== Search conformers/usages ==\n'
rg -n "CAPBridgeProtocol|:.*CAPBridgeProtocol|conform.*CAPBridgeProtocol" ios -g '*.swift'

Repository: Cap-go/capacitor-plus

Length of output: 1955


🏁 Script executed (no clone):

#!/bin/bash
set -euo pipefail

base="https://raw.githubusercontent.com/Cap-go/capacitor-plus"

printf '\n== CAPBridgeProtocol.swift (default branch) ==\n'
curl -fsSL "$base/main/ios/Capacitor/Capacitor/CAPBridgeProtocol.swift" | sed -n '1,180p'

printf '\n== Search GitHub code for CAPBridgeProtocol ==\n'
curl -fsSL "https://api.github.com/search/code?q=repo:Cap-go/capacitor-plus+CAPBridgeProtocol+in:file" | jq '.total_count, .items[]?.path' 2>/dev/null || true

Length of output: 146


🌐 Web query:

Cap-go/capacitor-plus CAPBridgeProtocol registerCallInterceptor Swift

💡 Result:

Capacitor-plus (maintained by the Capgo team) is designed to be API-compatible with official Capacitor [1]. It uses the same underlying Capacitor iOS core architecture, including the CAPBridgeProtocol [2][3][4]. There is no public method named registerCallInterceptor within the CAPBridgeProtocol or the Capacitor iOS core [3][5]. In Capacitor (and by extension, Capacitor-plus), communication between JavaScript and native Swift/Objective-C is handled through the standard plugin architecture [6][7]. If you need to intercept calls or monitor plugin execution, the following standard approaches are typically used instead of a direct interceptor method: 1. Plugin Method Implementation: Your Swift class inherits from CAPPlugin, and you define your methods using @objc [6][8]. These methods receive a CAPPluginCall object, allowing you to inspect the arguments and handle the execution logic [6][8]. 2. CAPPlugin Event Listeners: You can use addEventListener and removeEventListener within your plugin to manage communication [9]. 3. Extending the Bridge or ViewController: If you need to perform actions during the bridge's lifecycle, you can override methods such as capacitorDidLoad in your CAPBridgeViewController [10][6]. If you are seeing a reference to registerCallInterceptor, it may be part of a custom third-party extension or a misunderstanding of the internal bridge APIs, which are intentionally kept limited and often marked internal to preserve architectural stability [11]. Because Capacitor-plus syncs with the upstream Capacitor main branch, you can rely on the official Capacitor documentation for all iOS plugin development patterns [1][6][8].

Citations:


Public protocol addition is source-breaking.

registerCallInterceptor(_:handler:) is now a required CAPBridgeProtocol member, so any downstream conformer must implement it to keep compiling. If compatibility matters, make it optional or add a default implementation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ios/Capacitor/Capacitor/CAPBridgeProtocol.swift` around lines 82 - 84, The
new CAPBridgeProtocol requirement registerCallInterceptor(_:handler:) is
source-breaking for existing conformers. Update the protocol so this API is not
required for all adopters, either by moving the behavior into a protocol
extension with a default implementation or by making the interceptor
registration optional in CAPBridgeProtocol while keeping CAPBridge-related call
interception functionality available.

Comment on lines +94 to 110
/// This function must be called after plugins are loaded or it will have no effect.
open func updateAppLocationIfNeeded() {
let cordovaPlugin = bridge?.plugin(withName: "__CordovaPlugin")
let cordovaDeployDisabled = cordovaPlugin?.perform(Selector(("cordovaDeployDisabled"))).takeUnretainedValue() as? Bool ?? false

if !isNewBinary && !cordovaDeployDisabled {
if let persistedPath = KeyValueStore.standard["serverBasePath", as: String.self], !persistedPath.isEmpty {
if let libPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).first {
descriptor.appLocation = URL(fileURLWithPath: libPath, isDirectory: true)
let serverBasePath = URL(fileURLWithPath: libPath, isDirectory: true)
.appendingPathComponent("NoCloud")
.appendingPathComponent("ionic_built_snapshots")
.appendingPathComponent(URL(fileURLWithPath: persistedPath, isDirectory: true).lastPathComponent)
setServerBasePath(path: serverBasePath.path)
}
}
}
return descriptor
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -e swift -e m CordovaPlugin --exec rg -nP 'cordovaDeployDisabled' {}

Repository: Cap-go/capacitor-plus

Length of output: 1984


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Files mentioning __CordovaPlugin or cordovaDeployDisabled ==\n'
rg -n --hidden --glob '!**/.git/**' '__CordovaPlugin|cordovaDeployDisabled' .

printf '\n== Swift/Objective-C declarations around Cordova plugin usage ==\n'
fd -a -e swift -e m -e h . . | xargs -r rg -n --hidden --glob '!**/.git/**' 'cordovaDeployDisabled|__CordovaPlugin|plugin\(withName:'

Repository: Cap-go/capacitor-plus

Length of output: 1955


🌐 Web query:

"cordovaDeployDisabled" "__CordovaPlugin" Capacitor iOS

💡 Result:

In Capacitor, cordovaDeployDisabled and CordovaPlugin are technical components related to the integration and handling of Cordova plugins within the Capacitor framework [1][2]. cordovaDeployDisabled This is a configuration property used in older versions of Capacitor (and still present in the codebase for compatibility) to control the behavior of Cordova-related deployments [1][3]. It maps to the Cordova preference DisableDeploy [3][4][5]. When set to true, it indicates that the standard Cordova deployment or "hot-patching" mechanism (often associated with plugins like cordova-plugin-ionic-webview or legacy deploy services) should be disabled or bypassed [4]. Developers can configure this by adding the following to their capacitor.config.ts or capacitor.config.json file: { "cordova": { "preferences": { "DisableDeploy": "true" } } } Note that the value must typically be provided as the string "true" [4]. CordovaPlugin This is an internal identifier or class name used within the Capacitor architecture to manage Cordova compatibility [6][2]. In recent versions and refactors (including preparations for Capacitor 9), the framework moved away from direct Cordova wiring toward a more modular approach [2][7]. CordovaPlugin now acts as a central Capacitor plugin responsible for bootstrapping Cordova functionality, intercepting calls, and forwarding lifecycle events [2][7]. It replaces earlier, more tightly coupled systems for handling Cordova plugin initialization and communication [2][7]. Summary of Evolution These components reflect Capacitor's transition from an environment that tightly integrated with legacy Cordova infrastructure to one that treats Cordova compatibility as an isolated, modular layer [2][7]. If you encounter these terms, it is usually because you are either working with legacy configuration settings or interacting with the internal architectural abstraction layer that Capacitor uses to support Cordova plugins [4][2].

Citations:


🌐 Web query:

site:github.com/ionic-team/capacitor "cordovaDeployDisabled" "objc"

💡 Result:

The term "cordovaDeployDisabled" is an internal property used within the Capacitor framework (specifically in its iOS implementation) to determine whether the "DisableDeploy" preference from Cordova configurations should be honored [1][2]. In the Capacitor iOS codebase, this property is exposed as an @objc property [1][3] to allow interoperability between Swift components and Objective-C code [4]. It functions as follows: 1. Mapping: It checks the Capacitor configuration for a "DisableDeploy" setting (typically defined under cordova.preferences in the configuration file) [1][2]. 2. Logic: The property returns a boolean value [1][3]. If "DisableDeploy" is set to "true" in the project's configuration, cordovaDeployDisabled will evaluate to true [1][2]. 3. Usage: Capacitor uses this flag internally to control whether it should attempt to load and deploy web content from specific local paths (like ionic_built_snapshots), effectively allowing developers to disable the standard Cordova deployment behavior when desired [2][5]. To set this preference in a Capacitor project, developers typically add the following to their capacitor.config.json or capacitor.config.ts file [6]: { "cordova": { "preferences": { "DisableDeploy": "true" } } } It is important to note that the value must be provided as a string "true" [6]. The iOS layer then reads this configuration, and the internal @objc property reflects this state to the native bridge [1][4].

Citations:


Avoid perform(_:) for cordovaDeployDisabled

cordovaDeployDisabled is an @objc Bool property, so read it through KVC or a typed protocol instead. perform(_:) is undefined for scalar returns and can misread the BOOL as an object pointer, which can crash here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ios/Capacitor/Capacitor/CAPBridgeViewController.swift` around lines 94 - 110,
In CAPBridgeViewController.updateAppLocationIfNeeded, stop using perform(_:) on
__CordovaPlugin for cordovaDeployDisabled because it is an `@objc` Bool and the
current call can misread the scalar value. Read the property through KVC or a
typed protocol/cast on the plugin instance instead, then keep the existing
conditional logic using cordovaDeployDisabled unchanged.

let method = dict["action"] as? String ?? ""
let callbackId = dict["callbackId"] as? String ?? ""

let args = dict["actionArgs"] as? Array ?? []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Swift conditional cast as? Array without element type compile error generic parameter Element

💡 Result:

In Swift, attempting to use the conditional cast operator as? on an Array without specifying the element type—such as writing myArray as? Array or myArray as? [Any] (where the generic structure itself is the target)—will result in a compile-time error because Array is a generic type that requires its Element parameter to be defined [1][2]. The syntax Array or [Element] is not a concrete type in Swift; it is a generic type constructor [3]. To perform a conditional cast, the compiler must know exactly what type of elements you are attempting to cast into, as the runtime performs an element-by-element conversion [1][2]. Key reasons for this behavior include: 1. Mandatory Generic Parameters: Swift collections like Array<Element>, Set<Element>, and Dictionary<Key, Value> cannot exist without their generic parameters [3][2]. Attempting to use them without these parameters creates an incomplete type definition, which the compiler rejects [3]. 2. Element-wise Casting Mechanism: The as? operator for arrays is not a simple pointer cast. The Swift runtime treats an array cast as an element-by-element transformation [1][4]. It effectively iterates through the source array, attempts to cast each individual element to the target Element type, and constructs a new array if all elements succeed [1][2]. Because this logic requires knowledge of the target Element type to perform the cast, you must provide it explicitly [3]. If you are dealing with arrays of unknown types (e.g., [Any]), you must cast to a specific concrete array type, such as myArray as? [String] or myArray as? [Int], so the compiler and runtime understand the target type for the individual elements [1][2]. If the element type is truly unknown at compile time, you cannot perform this type of downcast, as the generic requirement cannot be satisfied [3]. Note that empty arrays can sometimes exhibit "magic" behavior where they appear to cast successfully to any array type [5][6]. This occurs because there are no elements to inspect, but the underlying type requirement remains the same; you should avoid relying on this behavior for logic control, as it can lead to unexpected results or crashes when the array is later populated [7][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file around the reported line.
sed -n '1,140p' ios/CapacitorCordova/CapacitorCordova/Classes/Public/Plugin.swift | nl -ba

# Search for similar casts in the repo for context.
rg -n --no-heading 'as\?\s*Array\b|as\?\s*\[[^]]+\]' ios -g '*.swift' || true

Repository: Cap-go/capacitor-plus

Length of output: 1955


🌐 Web query:

Swift let args = dict["actionArgs"] as? Array ?? [] compile error generic parameter Element could not be inferred

💡 Result:

The compile error "Generic parameter 'Element' could not be inferred" occurs because Array in Swift is a generic type that must know what kind of elements it contains [1][2]. When you use as? Array, you are attempting to cast to a non-specific array type without defining its Element type [3][1]. The compiler cannot infer this type from the context, so it requires you to be explicit [4][1]. To fix this, provide the specific type the array is expected to hold [1]. If you expect an array of strings, for example, use: let args = dict["actionArgs"] as? [String]?? [] If you do not know the exact type but know it contains objects that can be treated as generic items, use [Any]: let args = dict["actionArgs"] as? [Any]?? [] The syntax [Type] is shorthand for Array and is generally preferred in Swift [3][5][2]. By specifying the type, you provide the compiler with the necessary information to satisfy the generic parameter requirement [1][6].

Citations:


Specify the array element type in ios/CapacitorCordova/CapacitorCordova/Classes/Public/Plugin.swift:43 Array needs a concrete Element; as? Array won’t compile. Use [Any] here, or the actual element type if it’s known.

Fix
-            let args = dict["actionArgs"] as? Array ?? []
+            let args = dict["actionArgs"] as? [Any] ?? []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let args = dict["actionArgs"] as? Array ?? []
let args = dict["actionArgs"] as? [Any] ?? []
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ios/CapacitorCordova/CapacitorCordova/Classes/Public/Plugin.swift` at line
43, The cast in Plugin should use a concrete array element type instead of the
untyped Array, since `as? Array` will not compile. Update the `args` assignment
in `Plugin` to cast to `[Any]` (or the correct known element type) so the
`actionArgs` value can be read safely.

@RobinWitch RobinWitch left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This upstream sync regresses the fork's package identity, which will break beta and release publishing for Capacitor Plus.

The PR changes all workspace package names from the fork namespace back to upstream names:

core/package.json     @capacitor-plus/core    -> @capacitor/core
cli/package.json      @capacitor-plus/cli     -> @capacitor/cli
android/package.json  @capacitor-plus/android -> @capacitor/android
ios/package.json      @capacitor-plus/ios     -> @capacitor/ios

That is not just metadata. The PR beta publish workflow reads pkg.name from the selected workspace (.github/workflows/pr_beta_publish.yml lines 226-233 and 293), then runs npm publish in that package directory and adds a dist-tag using steps.version.outputs.package_name (lines 305-316). With these names, /publish-beta core would try to publish/tag @capacitor/core instead of @capacitor-plus/core, and the documented /publish-beta @capacitor-plus/core selector no longer matches any package name.

Please keep the @capacitor-plus/* package names while syncing the upstream code, otherwise the fork's beta publish path and downstream install commands point at the wrong npm namespace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.