Multi-process BFCache suspension for Site Isolation
41894db
Source/WebKit/UIProcess/SuspendedPageProxy.cpp
+void SuspendedPageProxy::startSuspension(std::optional<BackForwardFrameItemIdentifier> mainFrameItemID)
+{
+ ASSERT(m_suspensionState == SuspensionState::BeforeStart);
+ ASSERT(!m_browsingContextGroup->hasMultiplePages());
+
+ m_process->addSuspendedPageProxy(*this);
+ m_suspensionState = SuspensionState::Suspending;
+
+ if (mainFrameItemID)
+ suspendSubframeProcesses(*mainFrameItemID);
+ else
+ m_allSubframesSuspended = true;
+
+ m_messageReceiverRegistration.startReceivingMessages(m_process, m_webPageID, *this, *this);
+ m_suspensionTimeoutTimer.startOneShot(suspensionTimeout);
+ sendWithAsyncReply(Messages::WebPage::SetIsSuspended(true), [weakThis = WeakPtr { *this }](std::optional<bool> didSuspend) {
+ RefPtr protectedThis = weakThis.get();
+ if (!protectedThis || !didSuspend)
+ return;
+ protectedThis->didProcessRequestToSuspend(*didSuspend ? SuspensionState::Suspended : SuspensionState::FailedToSuspend);
+ });
+}
Source/WebKit/UIProcess/SuspendedPageProxy.cpp
+void SuspendedPageProxy::suspendSubframeProcesses(BackForwardFrameItemIdentifier mainFrameItemID)
+{
+ auto aggregator = MainRunLoopSuccessCallbackAggregator::create([weakThis = WeakPtr { *this }](bool success) {
+ RefPtr protectedThis = weakThis.get();
+ if (!protectedThis || protectedThis->m_suspensionState != SuspensionState::Suspending)
+ return;
+ if (!success) {
+ protect(protectedThis->backForwardCache())->removeEntry(*protectedThis);
+ return;
+ }
+ protectedThis->m_allSubframesSuspended = true;
+ protectedThis->maybeCompleteSuspension();
+ });
+
+ m_browsingContextGroup->forEachRemotePage(*page, [suspendedPage = Ref { *this }, &aggregator, mainFrameItemID](auto& remotePage) {
+ Ref process = remotePage.siteIsolatedProcess();
+ process->addSuspendedPageProxy(suspendedPage);
+ process->sendWithAsyncReply(Messages::WebPage::SetSubframesSuspended(true, mainFrameItemID), aggregator->chain(), remotePage.identifierInSiteIsolatedProcess());
+ });
+}
BFCache는 페이지를 벗어날 때 완전히 살아있는 snapshot을 보존하여 뒤로/앞으로 탐색 시 즉각적인 복원을 가능하게 합니다. Site Isolation 환경에서는 cross-origin iframe이 각각의 WebProcess 인스턴스에서 실행되며, 각 프로세스는 자체 per-process BackForwardCache singleton을 갖습니다. 이전까지 BFCache entry의 suspension은 완전히 단일 프로세스 방식으로만 동작했습니다.
이 commit은 UIProcess 내 SuspendedPageProxy를 coordinator로 확장합니다. 각 subframe의 WebProcess에 신규 SetSubframesSuspended IPC 메시지를 전송하며, 이때 main frame의 BackForwardFrameItemIdentifier를 함께 전달합니다. 이 식별자는 navigation entry마다 안정적으로 유지되는 키로, 각 WebProcess가 이 공유 키 아래에 자신의 CachedPage를 저장하는 데 사용됩니다. CallbackAggregator는 모든 프로세스에 걸친 완료 상태를 추적합니다. subframe 중 하나라도 suspension에 실패하면 BFCache entry가 제거되고 해당 subframe 프로세스들이 종료됩니다.
UIProcess WebProcess (main) WebProcess (subframe N)
│ │ │
├─ startSuspension() │ │
│ │ │ │
│ ├──► SetIsSuspended(true) ────►│ addIfCacheable() │
│ │ │ (HistoryItem path) │
│ │ │ │
│ ├──► SetSubframesSuspended ────┼───────────────────────►│
│ │ (mainFrameItemIdentifier) │ │ addIfCacheable(id, page)
│ │ │ │
│ └─ CallbackAggregator tracks all completions │
│ │ │ │
│ any fail? ◄───────────────┴────────────────────────┘
│ └──► removeEntry(*this)
│ teardown subframe processes
Significance
BFCache를 Site Isolation 환경으로 확장하는 중요한 아키텍처 변경입니다. 다수의 WebProcess에 걸쳐 UIProcess 생명주기 조율이 동시에 이루어지며, 새로운 IPC surface, cross-process 공유 식별자, 그리고 보안에 민감한 navigation 인프라 내의 새로운 teardown 경로가 도입되었습니다.
Audit directions
Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaaaaaaaaaa a Aa Aaaa Aaaaaaaaaaaaa Aaaaaa Aaa Aaaaaaaaaa Aa Aaaaaa Aaa Aaa Aaaaaaaaaaa Aa Aaaaaaaaaa Aaa Aaaa Aa Aaaaaaaaa Aaaaa Aaaaaaaaaa Aaaaaaaa Aaa Aaaa Aa Aaaa a Aaaa Aaaaa
Aaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaa Aaa Aa Aaa Aaaaaa Aa Aaaaaaaaa Aaaa Aa Aaaaaaaaaaaaaaaaaaaaa Aaaa Aaa Aa Aa Aaa Aaaaaaaaa Aa Aaa Aaaa Aaaa a Aaaa Aaaaa
Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aa Aaaaaaaa Aa Aaaaaa Aaaaaaaaaaaaaaa Aaa Aaaaaa Aaaaaaaaaa Aaaa Aaaaaaaaa Aaa a Aa Aaaaaa Aaaaaa Aaaa Aaa Aa Aaaaaaaaaaaaaaa Aaaa Aa Aaaa a Aaa Aaa Aaa Aaaaa
Aa a Aaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa a Aaa Aa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaa Aaa Aaaaaa Aaaaaaa Aaaaaaaa Aaaaa Aaaa Aaaa Aaaaaaaaaa Aaaaaa Aaa Aaa Aaa Aaaaa Aaaaaaaa Aaaaaa Aaaaaaaaaaaaa Aaaaaaaaaaa a Aa Aa a Aaaaa a Aa Aaaaa Aaa Aaaa Aaaaaaaaa Aaaaaaa Aaa Aaaa Aaaaa
🔒New cross-process lifecycle paths and IPC surface introduce several edge cases worth security investigation.
더 확인하려면 구독해 주세요