[visionOS] Introduce Connected Volumetric Scenes
Component: WebKit visionOS model element / Spatial Portal | a216b77
LayoutTests/model-element/volumetric/resources/volumetric-utils.js
LayoutTests/model-element/volumetric/volumetric-scene-api-disabled.html
visionOS에서 <model> content는 별도의 ModelProcess(RealityKit)가 rendering합니다. WebContent는 player proxy와 layer hosting context만 보유하며, UI process가 이를 page에 composite합니다. 한편 spatial: portal element는 하위 model들을 SpatialPortalController 아래에 묶어 관리합니다. 별도의 volumetric window에 표시하려면, 평소 page가 점유하던 layer hosting context를 UI process가 새로 생성한 UIScene에 넘겨야 합니다. 이때 생성된 scene은 자신을 요청한 request와 다시 짝지어져야 합니다.
이 commit은 실험적 기능인 Connected Volumetric Scenes를 추가했습니다. 기본값은 비활성화 상태입니다. 먼저 spatial: portal element와 단독 <model> element를 대상으로, Element에 requestVolumetricScene()과 exitVolumetricScene()이 노출되었습니다. 이를 호출하면 page가 계속 동작하는 상태에서 model content가 별도의 volumetric window에 표시됩니다. 새로 추가된 ElementVolumetricScene은 호출을 SpatialPortalController 또는 HTMLModelElement로 분기합니다.
또한 기존의 immersive detach flag는 inline, immersive, volumetric을 통합한 ModelPresentationMode로 대체되었습니다. enter, exit, resize는 새 message를 통해 WebPage, WebPageProxy, ModelProcessModelPlayer, ModelProcessModelPlayerProxy를 거쳐 전달됩니다. 결과적으로 UI process는 새로운 WKPortalVolumetricSceneController 안에서 model process의 layer를 hosting하게 됩니다.
WebContent UIProcess ModelProcess
│ │ │
│ requestVolumetricScene() │ │
│ (transient activation │ │
│ consumed) │ │
├─ enterVolumetricScene… ─────►│ presentVolumetricScene │
│ (scene-limit check first) │ ├─ create token + pending ctrl │
│ │ ├─ activate UIScene(token) │
│ │ │ └─ scene:willConnect… │
│ │ │ match token → ctrl │
│ │ └─ hostContent(ctx, pid) ──────►│ layer hosted in
│ │ │ volume
│◄─ updateVolumetricSceneSize ─┤ volume size change │
│ │ │
│◄─ volumetricSceneDidClose ───┤ window closed / dismissed │
│ (also on navigation/detach │ │
│ → dismissVolumetricScenes…) │ │
Significance
Page가 보유하던 layer hosting context를 UI process 소유의 window로 옮기는, web에서 도달 가능한 신규 API입니다. 이와 함께 WebContent, ModelProcess, UIProcess를 잇는 IPC와 token 기반 scene activation flow가 추가되었습니다.
Audit directions
새로 생긴 surface는 DOM API에서 시작해 WebPage, WebPageProxy IPC, PortalPresentationManagerProxy, WKPortalVolumetricSceneController로 이어집니다. 이와 병렬로 ModelProcessModelPlayerProxy로 향하는 message 경로도 존재합니다.
- Context 소유권. Volumetric scene에 진입하면 page는 자신의 점유를 해제하고, 새 scene이 layer hosting context를 가져갑니다. Page, model process, UI process가 이 context를 동시에 보유하거나 사용할 수 없는지 확인해야 합니다. 해제 이후에 여전히 사용할 수 있는 경로가 없는지도 함께 살펴볼 필요가 있습니다.
- Lifecycle race. Element 제거, navigation(
dismissVolumetricScenesForDetachedElements,didCommitLoad), document visibility 변화,volumetricSceneDidClose, 진행 중인 enter/reconnect 요청을 점검할 필요가 있습니다. 이때 stale element나 player reference가 남는지 확인해야 합니다. Double-close가 발생하거나 세 process 간 상태가 어긋나는 경우도 함께 살펴봐야 합니다. - Token 매칭. Scene의 user activity에 담긴 activation token과 pending-controller registry(
pendingSceneControllers,volumetricSceneTokenFromActivities)를 대상으로 위조, replay, 충돌 가능성을 점검해야 합니다. 대응하는 request 없이 연결된 scene을 안전하게 처리하는지도 확인이 필요합니다. - UI process 측 검증. Compromised WebContent process가 임의의
presentVolumetricScene,reconnect,dismissmessage를 전송하는 것은 이론적으로 가능합니다. 따라서 scene 개수 제한(page당 최대 1개)과 page별 소유권은 UI process에서 강제되어야 합니다.VolumetricSceneContentContext에 담긴 context ID, pid, 크기 값에 대한 검증도 마찬가지로 UI process의 몫입니다. - 크기·transform 연산. Volume 크기 갱신 경로(
updateVolumetricPresentationSize,applyVolumetricPresentationTransform)를 살펴볼 필요가 있습니다. 0, NaN, 지나치게 큰 값, 음수가 entity transform으로 그대로 흘러 들어가지 않는지 확인해야 합니다. - Presentation mode 리팩터링.
setDetachedForImmersive/setImmersivePresentation이ModelPresentationMode로 대체되면서 immersive 경로도 함께 변경되었습니다. 그래서 immersive에서 volumetric으로 전환되는 경우나, model이 하나뿐인 portal 같은 경우에 invariant가 깨지지 않는지 점검할 필요가 있습니다.