Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
366 changes: 364 additions & 2 deletions android/dimina/src/main/kotlin/com/didi/dimina/api/media/ImageApi.kt

Large diffs are not rendered by default.

24 changes: 22 additions & 2 deletions android/dimina/src/main/kotlin/com/didi/dimina/common/PathUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import android.net.Uri
import android.webkit.MimeTypeMap
import java.io.File
import java.nio.file.Files

/**
* Author: Doslin
Expand All @@ -27,10 +28,29 @@ object PathUtils {
}

fun appUserRoot(context: Context, appId: String): File =
File(context.filesDir, "$FILE_SYSTEM_DIR/${validatedAppId(appId)}/$USER_DIR").apply { mkdirs() }
confinedStorageRoot(context.filesDir, validatedAppId(appId), USER_DIR)

fun appTempRoot(context: Context, appId: String): File =
File(context.cacheDir, "$FILE_SYSTEM_DIR/${validatedAppId(appId)}/$TEMP_DIR").apply { mkdirs() }
confinedStorageRoot(context.cacheDir, validatedAppId(appId), TEMP_DIR)

internal fun confinedStorageRoot(platformRoot: File, appId: String, leaf: String): File {
val canonicalPlatformRoot = platformRoot.canonicalFile
val directories = listOf(
File(canonicalPlatformRoot, FILE_SYSTEM_DIR),
File(canonicalPlatformRoot, "$FILE_SYSTEM_DIR/$appId"),
File(canonicalPlatformRoot, "$FILE_SYSTEM_DIR/$appId/$leaf"),
)
directories.forEach { directory ->
require(!Files.isSymbolicLink(directory.toPath())) { "application storage contains a symbolic link" }
Files.createDirectories(directory.toPath())
require(!Files.isSymbolicLink(directory.toPath())) { "application storage contains a symbolic link" }
val canonicalDirectory = directory.canonicalFile
require(canonicalDirectory.path.startsWith(canonicalPlatformRoot.path + File.separator)) {
"application storage escapes platform sandbox"
}
}
return directories.last().canonicalFile
}

fun appTempFile(context: Context, appId: String, relativePath: String): File =
confinedFile(appTempRoot(context, appId), relativePath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ class MiniApp private constructor() {
*
* @param appId The ID of the MiniProgram to clear resources for
*/
@androidx.annotation.MainThread
fun clear(appId: String) {
updateCheckRegistry.reset(appId)
synchronized(this) {
Expand All @@ -458,6 +459,9 @@ class MiniApp private constructor() {
localNetworkApi.clearApp(appId)
deviceNetworkApi.clearApp(appId)
fileApi.clearApp(appId)
// 正在后台写盘的 canvas 导出属于这一代 runtime;换代之后它的回调没有接收方,
// 已经发布的文件也不会有人来取。
com.didi.dimina.api.media.CanvasExportGeneration.invalidate(appId)

// Detach this generation immediately so a rapid reopen creates a fresh runtime, but place
// native engine destruction behind lifecycle messages already queued by Bridge.destroy().
Expand All @@ -475,6 +479,7 @@ class MiniApp private constructor() {
/**
* Clears all API resources and callbacks for all MiniPrograms
*/
@androidx.annotation.MainThread
fun clearAll() {
updateCheckRegistry.resetAll()
synchronized(this) {
Expand All @@ -490,6 +495,7 @@ class MiniApp private constructor() {
jsCoreMap.clear()
jsCoresToDestroy.forEach { (appId, jsCore) ->
LogUtils.d(tag, "Scheduling JsCore destruction for appId: $appId")
com.didi.dimina.api.media.CanvasExportGeneration.invalidate(appId)
jsCore.destroyAfterMessages()
}

Expand Down
Loading
Loading