Report the restored document's identity on back/forward cache commit
Component: WebCore Frame Loading | 63846dd
새로 로드하지 않고 back/forward cache에서 navigation이 제공되는 경우에는 호출 순서가 문제가 됩니다. FrameLoader::commitProvisionalLoad()는 cachedPage->restore()가 frame의 Document를 캐시된 쪽으로 교체하기 전에 dispatchDidCommitLoad()를 먼저 호출합니다. 그래서 dispatchDidCommitLoad() 안에서 frame의 현재 document를 읽는 코드는 모두 빠져나가는 document의 데이터를 읽게 됩니다. UI process는 이 데이터를 그대로 받아 사용합니다. 전달 경로는 WKFrameInfo._documentIdentifier, securityOrigin, PageLoadState::origin(), 그리고 WebDriver BiDi입니다. 결국 "이 frame이 지금 표시하고 있는 document가 무엇인가"에 대한 답으로 쓰이는 셈입니다.
이번 commit에서는 BackForwardCacheCommitData가 도입되었습니다. 복원된 document의 identifier, security origin, COOP/COEP 정책을 FrameLoader::dispatchDidCommitLoad()로 명시적으로 전달하는 역할을 맡습니다. 이미 hasInsecureContent, usedLegacyTLS, wasPrivateRelayed에 적용되어 있던 방식을 그대로 따릅니다. 그 결과 WebLocalFrameLoaderClient::dispatchDidCommitLoad()는 빠져나가는 document가 아니라 복원된 document의 identity를 보고하게 됩니다.
Significance
commit 작성자는 이 변경을 Site Isolation의 선결 과제로 지목합니다. UI process가 commit된 document identifier를 기준으로, web process에서 도착한 메시지가 현재 표시 중인 document에 해당하는지를 판단하게 되기 때문입니다. 현재로서는 stale identity가 사용자에게 드러나는 영향을 만들지 않습니다. 다만 해당 메커니즘이 실제로 반영되고 나면 성격이 달라집니다. 여기서 잘못된 identifier가 전달되는 것은 API 정확성 수준의 문제가 아니라 authorization bug에 해당하게 됩니다.
Audit directions
패턴을 한 줄로 정리하면, 설명하려는 상태 전환이 끝나기 전에 commit 시점 알림이 먼저 발생한다는 점입니다. 좁게 보면, dispatchDidCommitLoad()와 그 client 구현들이 frame의 현재 document에서 읽는 나머지 값들을 모두 나열해 볼 만합니다. 그리고 각각을 bfcache의 호출 순서와 대조해 점검합니다. 이미 명시적으로 전달되도록 배선된 필드들(hasInsecureContent, usedLegacyTLS, wasPrivateRelayed)은 앞서 누군가 같은 문제를 찾아낸 흔적에 해당합니다. 조금 더 넓히면, UI process 쪽에서 관찰되는 identity 값들이 대상이 됩니다. 인자로 전달받는 대신 lifecycle callback 안에서 직접 얻어지는 값은 동일한 순서 문제를 그대로 물려받기 때문입니다. 특히 UI process가 나중에 "이 메시지가 현재 표시 중인 대상에 해당하는가"를 판단할 때 사용하는 모든 값이 흥미로운 집합입니다. 가장 넓게 보면, 상태 교체와의 선후 관계가 구현 세부사항에 불과한 callback이 identity를 보고하는 경우가 문제입니다. 두 가지 순서 중 한쪽에서는 결국 틀린 값이 나오게 됩니다. 오래 가는 해법은 값을 인자로 전달하는 형태이며, 이번 commit이 택한 방식이 정확히 그것입니다. 코드 리뷰에서의 신호는 이렇습니다. 자신이 알리려는 load를 설명하기 위해 frame->document()를 호출하는 client 알림 메서드입니다.