Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
23ad7f8
Release 8.3.2
May 7, 2026
b2d7719
fix(cli): copy plugin files in CocoaPods projects (#8467)
jcesarmobile May 8, 2026
76ff70e
Release 8.3.3
May 8, 2026
b7e167b
chore(cli): update telemetry endpoint (#8464)
alexgerardojacinto May 12, 2026
de1e506
Release 8.3.4
May 12, 2026
731a82e
chore: format java code (#8475)
jcesarmobile May 21, 2026
bc74536
chore: format java code (#8477)
jcesarmobile May 21, 2026
93c72de
feat: add method getDouble to plugin config (#7638)
robingenz May 21, 2026
e456de0
fix(SystemBars): make `safe-area-inset-x` available on API <= 34 (#8424)
theproducer May 22, 2026
258867b
feat(cli): add experimental packageOptions (#8471)
jcesarmobile May 26, 2026
b4b297a
feat(cli): capture ios_package_manager in telemetry (#8482)
alexgerardojacinto May 27, 2026
1d031a4
fix(cli): revert live reload config on failure (#8485)
jcesarmobile May 28, 2026
f1077ef
chore: fix typo in declarations.ts (#8488)
jcesarmobile May 29, 2026
d4ad7ff
fix(SystemBars): respect `insetsHandling` disable (#8481)
theproducer Jun 1, 2026
4c6c321
fix(android): show only the requested system bar (#8480)
fallintoplace Jun 1, 2026
36b729d
chore: Decrease timeout for CI jobs from 60 to 30 minutes (#8476)
markemer Jun 1, 2026
41fd9de
Release 8.4.0
Jun 2, 2026
28bb2c6
fix(cli): patch Capacitor SPM dependency version in plugins (#8492)
jcesarmobile Jun 2, 2026
6048e90
fix(cli): make SPM dependency patch work on prereleases (#8508)
jcesarmobile Jun 15, 2026
7217b52
Release 8.4.1
Jun 19, 2026
b789b68
chore: run `npm run fmt` to fix lint errors (#8516)
markemer Jun 22, 2026
6f2d328
fix(android): explicitly grant URI permissions for image capture inte…
alexgerardojacinto Jul 8, 2026
1834b97
Release 8.4.2
Jul 14, 2026
f368a1b
chore(android): fix lint issues (#8542)
OS-pedrogustavobilro Jul 27, 2026
4c1c870
fix(cli): support TypeScript 7 when loading capacitor.config.ts (#8534)
conbrad Jul 28, 2026
3fa04a3
feat(ios): UIScene Support (#8536)
theproducer Jul 29, 2026
984fa85
feat(cli): add migrator functionality for adopting UIScene (#8544)
theproducer Jul 31, 2026
3ab4139
Release 8.5.0
Jul 31, 2026
5e5bb3b
fix(cli): use POSIX paths in CapApp-SPM Package.swift (#8549)
omriwil Aug 6, 2026
5ac4dd6
fix(core): prevent removeListener from removing wrong listener (#8271)
maniktyagi04 Aug 10, 2026
ee586ae
fix: block navigation to the internal HTTP proxy path
ItsChaceD Aug 31, 2026
0c9e35d
Release 8.5.1
Aug 31, 2026
c567328
fix(ios): do not forward scene lifecycle events to the page before it…
tgabi333 Sep 10, 2026
035b16a
fix(android): add null checks for plugin annotation when retrieving p…
robingenz Sep 10, 2026
e37d9c6
fix: resolve issues with safe area / systembars plugin (#8535)
tafelnl Sep 10, 2026
5e0f678
Release 8.5.2
Sep 11, 2026
8cf162f
fix(android): do not pad the WebView for the IME below API 30
ruffzy Sep 16, 2026
93206d2
chore: sync upstream PR #8606 from @ruffzy (upstream-preferred confli…
Sep 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ concurrency:
jobs:
setup:
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 30
steps:
- name: Get Latest
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand All @@ -38,7 +38,7 @@ jobs:
key: ${{ runner.OS }}-bun-dependencies-cache-${{ hashFiles('bun.lock') }}
lint:
runs-on: macos-15
timeout-minutes: 10
timeout-minutes: 30
steps:
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
Expand All @@ -57,7 +57,7 @@ jobs:
- run: bun run lint
test-cli:
runs-on: macos-15
timeout-minutes: 10
timeout-minutes: 30
needs:
- setup
- lint
Expand All @@ -81,7 +81,7 @@ jobs:
working-directory: ./cli
test-core:
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 30
needs:
- setup
- lint
Expand All @@ -105,7 +105,7 @@ jobs:
working-directory: ./core
test-ios:
runs-on: macos-15
timeout-minutes: 10
timeout-minutes: 30
needs:
- setup
- lint
Expand Down Expand Up @@ -136,7 +136,7 @@ jobs:
run: sh ./scripts/native-podspec.sh lint
test-android:
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 30
needs:
- setup
- lint
Expand Down
30 changes: 13 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,29 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [8.5.2](https://github.com/Cap-go/capacitor-plus/compare/8.5.1...8.5.2) (2026-08-26)

**Note:** Version bump only for package capacitor





## [8.5.1](https://github.com/Cap-go/capacitor-plus/compare/8.3.12...8.5.1) (2026-08-25)

## [8.5.2](https://github.com/ionic-team/capacitor/compare/8.5.1...8.5.2) (2026-09-11)

### Bug Fixes

* **ci:** fetch upstream objects so plus branch sync works ([#109](https://github.com/Cap-go/capacitor-plus/issues/109)) ([1fa7eee](https://github.com/Cap-go/capacitor-plus/commit/1fa7eeeff9494e9b32afb20a9850389b79d6bcec))
* **ci:** resolve modify/delete conflicts in sync conflict PRs ([#110](https://github.com/Cap-go/capacitor-plus/issues/110)) ([5c29fb9](https://github.com/Cap-go/capacitor-plus/commit/5c29fb9af001b9aafdcde7b7054585e093f44431))

- **android:** add null checks for plugin annotation when retrieving permissions ([#8400](https://github.com/ionic-team/capacitor/issues/8400)) ([035b16a](https://github.com/ionic-team/capacitor/commit/035b16aca15eab136efc49eaec64b45987cfefeb))
- **ios:** do not forward scene lifecycle events to the page before it has loaded ([#8595](https://github.com/ionic-team/capacitor/issues/8595)) ([c567328](https://github.com/ionic-team/capacitor/commit/c567328d0feb90c306ea824edc5a799bdfe26542))
- resolve issues with safe area / systembars plugin ([#8535](https://github.com/ionic-team/capacitor/issues/8535)) ([e37d9c6](https://github.com/ionic-team/capacitor/commit/e37d9c60785368acf2a83cfd4c20f47076672bdd))

## [8.5.1](https://github.com/ionic-team/capacitor/compare/8.5.0...8.5.1) (2026-08-31)

### Bug Fixes

- block navigation to the internal HTTP proxy path ([ee586ae](https://github.com/ionic-team/capacitor/commit/ee586ae680887ba99d066616f976db149542d922))
- **cli:** use POSIX paths in CapApp-SPM Package.swift ([#8549](https://github.com/ionic-team/capacitor/issues/8549)) ([5e5bb3b](https://github.com/ionic-team/capacitor/commit/5e5bb3befc312477900252ab07e23b596f8cb0d1))
- **core:** prevent removeListener from removing wrong listener ([#8271](https://github.com/ionic-team/capacitor/issues/8271)) ([5ac4dd6](https://github.com/ionic-team/capacitor/commit/5ac4dd613ae989d8dc8738ea25b77efbd4fa21fe))

# [8.5.0](https://github.com/ionic-team/capacitor/compare/8.4.2...8.5.0) (2026-07-31)

## Bug Fixes
### Bug Fixes

- **cli:** support TypeScript 7 when loading capacitor.config.ts ([#8534](https://github.com/ionic-team/capacitor/issues/8534)) ([4c1c870](https://github.com/ionic-team/capacitor/commit/4c1c8709413b9c19b008c99122ca330cc3c90e6f))

## Features
### Features

- **cli:** add migrator functionality for adopting UIScene ([#8544](https://github.com/ionic-team/capacitor/issues/8544)) ([984fa85](https://github.com/ionic-team/capacitor/commit/984fa85ba0adab0aacf895aed6323bf4b503dccb))
- **ios:** UIScene Support ([#8536](https://github.com/ionic-team/capacitor/issues/8536)) ([3fa04a3](https://github.com/ionic-team/capacitor/commit/3fa04a357c92af34cd6fccb8124791963804a9dc))
Expand All @@ -49,14 +45,14 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline

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

## Bug Fixes
### 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))
- **cli:** revert live reload config on failure ([#8485](https://github.com/ionic-team/capacitor/issues/8485)) ([1d031a4](https://github.com/ionic-team/capacitor/commit/1d031a4abec2c793079ba8897ad2e40c4cc6c7f9))
- **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
### Features

- add method getDouble to plugin config ([#7638](https://github.com/ionic-team/capacitor/issues/7638)) ([93c72de](https://github.com/ionic-team/capacitor/commit/93c72de40a2ec4c78b33659250cb08340083088e))
- **cli:** add experimental packageOptions ([#8471](https://github.com/ionic-team/capacitor/issues/8471)) ([258867b](https://github.com/ionic-team/capacitor/commit/258867b7bf37b1837b99b02ec9638e5a6df08d97))
Expand Down
17 changes: 7 additions & 10 deletions android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [8.5.2](https://github.com/Cap-go/capacitor-plus/compare/8.5.1...8.5.2) (2026-08-26)
## [8.5.2](https://github.com/ionic-team/capacitor/compare/8.5.1...8.5.2) (2026-09-11)

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





## [8.5.1](https://github.com/Cap-go/capacitor-plus/compare/8.3.12...8.5.1) (2026-08-25)

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

- **android:** add null checks for plugin annotation when retrieving permissions ([#8400](https://github.com/ionic-team/capacitor/issues/8400)) ([035b16a](https://github.com/ionic-team/capacitor/commit/035b16aca15eab136efc49eaec64b45987cfefeb))
- resolve issues with safe area / systembars plugin ([#8535](https://github.com/ionic-team/capacitor/issues/8535)) ([e37d9c6](https://github.com/ionic-team/capacitor/commit/e37d9c60785368acf2a83cfd4c20f47076672bdd))

## [8.5.1](https://github.com/ionic-team/capacitor/compare/8.5.0...8.5.1) (2026-08-31)

### Bug Fixes

- block navigation to the internal HTTP proxy path ([ee586ae](https://github.com/ionic-team/capacitor/commit/ee586ae680887ba99d066616f976db149542d922))

# [8.5.0](https://github.com/ionic-team/capacitor/compare/8.4.2...8.5.0) (2026-07-31)

Expand Down
10 changes: 10 additions & 0 deletions android/capacitor/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application>
<activity
android:name="com.getcapacitor.android.TestHostActivity"
android:theme="@style/AppTheme.NoActionBar"
android:exported="false" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.getcapacitor.android;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import android.net.Uri;
import android.webkit.WebResourceRequest;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.getcapacitor.Bridge;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
* The proxy path shares the app's host and scheme, so the host/scheme guard alone would let it
* load in the WebView.
*/
@RunWith(AndroidJUnit4.class)
public class HttpInterceptorNavigationTest {

private static final String INTERCEPTOR_URL =
"https://localhost" + Bridge.CAPACITOR_HTTP_INTERCEPTOR_START + "?u=https://example.com/payload.html";
private static final String IN_APP_URL = "https://localhost/index.html";
private static final String EXTERNAL_URL = "https://example.com/";

/** A plugin registered by the test host returns "allow" for the proxy path; it must not win. */
@Test
public void blocksNavigationToInterceptorPath() {
try (ActivityScenario<TestHostActivity> scenario = ActivityScenario.launch(TestHostActivity.class)) {
scenario.onActivity((activity) -> {
Bridge bridge = activity.getBridge();
assertNotNull(bridge);
assertTrue("interceptor navigation must be blocked", bridge.launchIntent(Uri.parse(INTERCEPTOR_URL)));
assertFalse("in-app navigation must stay in the WebView", bridge.launchIntent(Uri.parse(IN_APP_URL)));
assertTrue("external navigation must leave the WebView", bridge.launchIntent(Uri.parse(EXTERNAL_URL)));
});
}
}

/** An iframe looks like a fetch to isForMainFrame(), so subframe documents must be refused too. */
@Test
public void refusesProxyForDocumentRequests() {
try (ActivityScenario<TestHostActivity> scenario = ActivityScenario.launch(TestHostActivity.class)) {
scenario.onActivity((activity) -> {
Bridge bridge = activity.getBridge();
assertNotNull(bridge);
// Without this the proxy refuses everything and the assertions below prove nothing.
assertTrue(
"CapacitorHttp must be enabled for this test to mean anything",
bridge.getConfig().getPluginConfiguration("CapacitorHttp").getBoolean("enabled", false)
);

Map<String, String> navHeaders = new HashMap<>();
navHeaders.put("Accept", "text/html,application/xhtml+xml");
navHeaders.put("Upgrade-Insecure-Requests", "1");

assertNull(
"main frame document must be refused",
bridge.getLocalServer().shouldInterceptRequest(new FakeRequest(INTERCEPTOR_URL, true, navHeaders))
);
assertNull(
"iframe document must be refused",
bridge.getLocalServer().shouldInterceptRequest(new FakeRequest(INTERCEPTOR_URL, false, navHeaders))
);
});
}
}

private static class FakeRequest implements WebResourceRequest {

private final Uri url;
private final boolean mainFrame;
private final Map<String, String> headers;

FakeRequest(String url, boolean mainFrame, Map<String, String> headers) {
this.url = Uri.parse(url);
this.mainFrame = mainFrame;
this.headers = headers;
}

@Override
public Uri getUrl() {
return url;
}

@Override
public boolean isForMainFrame() {
return mainFrame;
}

@Override
public boolean isRedirect() {
return false;
}

@Override
public boolean hasGesture() {
return false;
}

@Override
public String getMethod() {
return "GET";
}

@Override
public Map<String, String> getRequestHeaders() {
return headers;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.getcapacitor.android;

import android.net.Uri;
import com.getcapacitor.Bridge;
import com.getcapacitor.Plugin;
import com.getcapacitor.annotation.CapacitorPlugin;

/** A plugin that tries to allow the proxy path. The navigation guard must ignore it. */
@CapacitorPlugin(name = "InterceptorAllowingPlugin")
public class InterceptorAllowingPlugin extends Plugin {

@Override
public Boolean shouldOverrideLoad(Uri url) {
String path = url.getPath();
if (path != null && path.startsWith(Bridge.CAPACITOR_HTTP_INTERCEPTOR_START)) {
return false; // "allow this navigation"
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.getcapacitor.android;

import com.getcapacitor.BridgeActivity;
import com.getcapacitor.CapConfig;
import org.json.JSONException;
import org.json.JSONObject;

/**
* Host for instrumented tests. CapacitorHttp is on so the proxy is reachable, and a plugin that
* tries to allow the proxy path is registered so tests can prove the guard still wins.
*/
public class TestHostActivity extends BridgeActivity {

@Override
protected void load() {
registerPlugin(InterceptorAllowingPlugin.class);

try {
JSONObject plugins = new JSONObject("{\"CapacitorHttp\":{\"enabled\":true}}");
config = new CapConfig.Builder(this).setPluginsConfiguration(plugins).create();
} catch (JSONException e) {
throw new IllegalStateException("bad test plugin config", e);
}

super.load();
}
}
6 changes: 0 additions & 6 deletions android/capacitor/src/main/assets/native-bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -417,12 +417,6 @@ var nativeBridge = (function (exports) {
}
};
const platform = getPlatformId(win);
if (platform == 'android' && typeof win.CapacitorSystemBarsAndroidInterface !== 'undefined') {
// add DOM ready listener for System Bars
document.addEventListener('DOMContentLoaded', function () {
win.CapacitorSystemBarsAndroidInterface.onDOMReady();
});
}
if (platform == 'android' || platform == 'ios') {
// patch document.cookie on Android/iOS
win.CapacitorCookiesDescriptor =
Expand Down
10 changes: 10 additions & 0 deletions android/capacitor/src/main/java/com/getcapacitor/Bridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,12 @@ private int extractWebViewMajorVersion(final PackageManager pm, final String web
}

public boolean launchIntent(Uri url) {
// The proxy returns a remote body at the app origin, so block it before plugins can allow it.
String path = url.getPath();
if (path != null && path.startsWith(CAPACITOR_HTTP_INTERCEPTOR_START)) {
return true;
}

/*
* Give plugins the chance to handle the url
*/
Expand Down Expand Up @@ -1262,6 +1268,10 @@ protected Map<String, PermissionState> getPermissionStates(Plugin plugin) {
}
}
}
} else {
Logger.warn(
String.format("getPermissionStates: missing @CapacitorPlugin annotation for plugin %s", plugin.getPluginHandle().getId())
);
}

return permissionsResults;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,12 +412,6 @@ private boolean showImageCapturePicker(final ValueCallback<Uri[]> filePathCallba
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Store in static variables to survive activity recreation
pendingFilePathCallback = filePathCallback;
pendingImageFileUri = imageFileUri;
pendingFileChooserType = FileChooserType.IMAGE_CAPTURE;

activityListener = (activityResult) -> {
Uri[] result = null;
if (activityResult.getResultCode() == Activity.RESULT_OK) {
Expand Down
13 changes: 9 additions & 4 deletions android/capacitor/src/main/java/com/getcapacitor/Plugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -502,10 +502,14 @@ protected void requestPermissionForAliases(@NonNull String[] aliases, @NonNull P
private String[] getPermissionStringsForAliases(@NonNull String[] aliases) {
CapacitorPlugin annotation = handle.getPluginAnnotation();
HashSet<String> perms = new HashSet<>();
for (Permission perm : annotation.permissions()) {
if (Arrays.asList(aliases).contains(perm.alias())) {
perms.addAll(Arrays.asList(perm.strings()));
if (annotation != null) {
for (Permission perm : annotation.permissions()) {
if (Arrays.asList(aliases).contains(perm.alias())) {
perms.addAll(Arrays.asList(perm.strings()));
}
}
} else {
Logger.warn(String.format("getPermissionStringsForAliases: missing @CapacitorPlugin annotation for plugin %s", handle.getId()));
}

return perms.toArray(new String[0]);
Expand Down Expand Up @@ -1003,7 +1007,8 @@ protected void handleOnDestroy() {}
* Give the plugins a chance to take control when a URL is about to be loaded in the WebView.
* Returning true causes the WebView to abort loading the URL.
* Returning false causes the WebView to continue loading the URL.
* Returning null will defer to the default Capacitor policy
* Returning null will defer to the default Capacitor policy.
* Not called for Capacitor's internal HTTP proxy path, which is always blocked.
*/
@SuppressWarnings("unused")
public Boolean shouldOverrideLoad(Uri url) {
Expand Down
Loading
Loading