Skip to content

Commit f373d50

Browse files
committed
ADFA-3598: address CodeRabbit review feedback
- PreviewLayoutAction: catch Exception (not Throwable) and log on resource-path parse failure; derive the layout base path from the last "layout/" segment instead of substringBefore("layout") - EditorHandlerActivity: rebuild EDITOR_TOOLBAR plugin actions on plugin disable so stale PluginToolbarActionItem callbacks are cleared - IdeProjectServiceImpl: path-validate getModuleContext via isPathAllowed() - ToolbarAction: document why the provider callbacks stay body vars (ABI compat) Deferred: permission-gating IdeBuildService.executeTasks needs a per-plugin permission-aware wrapper + a new build permission (build service is a shared singleton); to be done as a focused security change.
1 parent 664062d commit f373d50

4 files changed

Lines changed: 18 additions & 2 deletions

File tree

‎app/src/main/java/com/itsaky/androidide/actions/etc/PreviewLayoutAction.kt‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ class PreviewLayoutAction(context: Context, override val order: Int) : EditorRel
8181
if (file != null && !viewModel.isInitializing && file.name.endsWith(".xml")) {
8282
val type = try {
8383
extractPathData(file).type
84-
} catch (err: Throwable) {
84+
} catch (err: Exception) {
85+
LOG.warn("Failed to parse resource path for '{}'; hiding preview action", file.name, err)
8586
markInvisible()
8687
return
8788
}
@@ -146,7 +147,7 @@ class PreviewLayoutAction(context: Context, override val order: Int) : EditorRel
146147

147148
private fun EditorHandlerActivity.previewXmlLayout(file: File) {
148149
val intent = Intent(this, EditorActivity::class.java)
149-
intent.putExtra(Constants.EXTRA_KEY_FILE_PATH, file.absolutePath.substringBefore("layout"))
150+
intent.putExtra(Constants.EXTRA_KEY_FILE_PATH, file.absolutePath.substringBeforeLast("layout${File.separator}"))
150151
intent.putExtra(Constants.EXTRA_KEY_LAYOUT_FILE_NAME, file.name.substringBefore("."))
151152
uiDesignerResultLauncher?.launch(intent)
152153
}

‎app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ import com.itsaky.androidide.ui.CodeEditorView
9292
import com.itsaky.androidide.fragments.sidebar.EditorSidebarFragment
9393
import com.itsaky.androidide.utils.DialogUtils.newMaterialDialogBuilder
9494
import com.itsaky.androidide.utils.DialogUtils.showConfirmationDialog
95+
import com.itsaky.androidide.utils.EditorActivityActions
9596
import com.itsaky.androidide.utils.EditorSidebarActions
9697
import com.itsaky.androidide.utils.IntentUtils.openImage
9798
import com.itsaky.androidide.utils.UniqueNameBuilder
@@ -1269,6 +1270,8 @@ open class EditorHandlerActivity :
12691270
(supportFragmentManager.findFragmentById(R.id.drawer_sidebar) as? EditorSidebarFragment)
12701271
?.let { EditorSidebarActions.setup(it) }
12711272

1273+
EditorActivityActions.register(this)
1274+
12721275
invalidateOptionsMenu()
12731276

12741277
Log.i("EditorHandlerActivity", "Tore down contributions for disabled plugin: $pluginId")

‎plugin-api/src/main/kotlin/com/itsaky/androidide/plugins/extensions/UIExtension.kt‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ data class ToolbarAction(
139139
val order: Int = 0,
140140
val action: () -> Unit
141141
) {
142+
// NOTE: the provider callbacks below are intentionally body `var` properties rather than
143+
// primary-constructor parameters. Adding constructor params would change the synthesized
144+
// <init>/copy()/componentN signatures and break ABI for plugins already compiled against the
145+
// shipped plugin-api — the exact pattern [MenuItem] uses for the same reason. The trade-off
146+
// (copy()/equals() ignore these providers) is acceptable: plugins build ToolbarAction directly
147+
// and the host never copies it. Do NOT move these into the constructor.
148+
142149
/**
143150
* Optional callback to compute the enabled state dynamically at render time.
144151
* When null, the static [isEnabled] is used. Mirrors the [MenuItem] providers.

‎plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/services/IdeProjectServiceImpl.kt‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ class IdeProjectServiceImpl(
8686
throw SecurityException("Plugin $pluginId does not have required permissions: ${getRequiredPermissionsString()}")
8787
}
8888

89+
val path = File(filePath)
90+
if (!isPathAllowed(path)) {
91+
throw SecurityException("Plugin $pluginId does not have access to path: ${path.absolutePath}")
92+
}
93+
8994
return try {
9095
ModuleContextResolver.resolve(filePath)
9196
} catch (e: Exception) {

0 commit comments

Comments
 (0)