[Site Isolation] Enable same-site BFCache with cross-site iframes via UIProcess coordination
Site Isolation은 cross-origin iframe을 별도의 WebContent process에서 실행합니다. 이 구조에서 BFCache'd 페이지를 suspend하거나 restore하려면 임의 개수의 renderer process를 병렬로 조율해야 합니다. BFCache는 DOM, JS heap, media 상태를 포함한 페이지 전체 snapshot을 보존해 뒤로/앞으로 탐색을 즉각적으로 만드는 메커니즘입니다. 기존에는 cross-site iframe이 포함된 페이지가 BFCache 대상에서 단순히 제외되었습니다.
Source/WebCore/loader/FrameLoader.cpp
이 commit에서는 UIProcess를 BFCache의 유일한 권한 보유자로 지정합니다. ShouldRestoreFromBackForwardCache 신호는 Yes/No/Unspecified 세 가지 값으로 처리됩니다. Cache 시점에는 UIProcess가 live frame tree를 순회하며 각 iframe process에 SuspendWithFrameItem을 전달합니다. Restore 시점에는 takeForRestoration()이 소유권을 원자적으로 취득한 뒤, commit 전에 각 iframe process에 RestoreWithFrameItem을 전달합니다. Site Isolation을 사용하지 않는 기존 경로는 ::Unspecified를 전달해 기존 hasCachedPage 처리 방식을 그대로 사용합니다. 한편 사용자가 이미 뒤로 탐색한 이후에 도착하는 DidCacheBackForwardItem IPC는 race guard가 처리합니다.
Significance
이 변경은 Site Isolation 환경에서 BFCache가 동작하는 구조적 토대를 확립합니다. Cache lifecycle 권한은 WebProcess에서 UIProcess로 이전되었습니다. 또한 여러 renderer process에 걸쳐 새로운 ownership 의미 체계(takeForRestoration(), m_pagesPendingClose 방식의 mirror entry)가 도입되었습니다.
Audit directions
주목해야 할 지점이 여러 곳 있습니다. (1) didCacheBackForwardItem의 race guard는 cached item의 URL을 pageLoadState.pendingAPIRequestURL()과 비교합니다. fragment, 후행 슬래시, 인코딩 등 URL 정규화 방식의 차이로 false negative가 발생할 가능성이 있습니다. 이 경우 UIProcess에 stale mirror entry가 남게 됩니다. (2) markAsTakenForRestoration()은 m_backForwardFrameItemID를 초기화해 destructor의 ClearCachedPage IPC를 억제합니다. 잘못된 entry에 호출되거나 destructor와 race가 발생하면, WebProcess는 이미 사용된 것으로 간주된 cached Page를 계속 보유하게 됩니다. (3) takeForRestoration()이 주장하는 원자성이 iframe process 수집과 child entry 처리 모두를 하나의 lock 하에서 보장하는지 확인해야 합니다. (4) ::No 경로는 WebProcess 측 entry를 제거하지만, 이미 iframe으로 전송 중인 RestoreWithFrameItem이 존재할 가능성이 있습니다. (5) DidCommitLoadForFrame을 통해 전달되는 RestoredFromBackForwardCache 값은 iframe subtree 재연결을 제어합니다. 이 값이 조작되거나 잘못 전달되면, 탐색 간에 iframe 상태가 혼용될 가능성이 있습니다.