findStringMatches is only sent to the main frame's process.
Component: WebKit Site Isolation | b2c0cb3
Source/WebKit/UIProcess/WebPageProxy.cpp
Under site isolation, the main frame's process sees cross-origin iframes only as remote-frame proxies, so page-wide find has to be coordinated by the trusted UIProcess (WebPageProxy). Follow-up actions (select, indicate, snapshot, replace) address a match by integer index, which UIProcess must now translate into a (frame, process-local index) pair built from data untrusted WebContent processes report.
WebPageProxy::findStringMatches now fans out to every WebContent process. Each returns matches grouped by frame, plus the selection frame and the selection's index within it (FindSelectionInFrame). UIProcess merges in frame-tree order, caps at maxMatchCount, and keeps a global-index to (frameID, local index) table that selectFindMatch, indicateFindMatch, getImageForFindMatch and replaceMatches use for routing. A new UpdateFindUIAfterFindingAllMatches IPC updates find UI once all results are in.
per-WCP reply { [(frameID, rects)], selectionInFrame{frameID, idx} }
└─► walk UI frame tree in order ─► cap at maxMatchCount
└─► m_findMatchLocations: globalIdx -> (frameID, indexInProcess)
follow-up: globalIdx ─► bounds-checked lookup ─► frameID
─► process resolved from UI frame tree at send time ─► send indexInProcess
Significance
Find-in-page previously missed matches in cross-origin iframes under site isolation. The UIProcess now builds cross-process routing state from frame IDs and indices supplied by untrusted WebContent processes. Out-of-range selection and global indices are already bounds-checked (firstIndexAfterSelection, findMatchLocation).
Audit directions
- Unowned frame IDs in replies.
didFindStringMatchesnever checks that a reportedFrameIdentifierbelongs to the replying process, andm_frameMatches.set/m_selectionIndices.setoverwrite, so a compromised renderer can contribute or replace entries for frames it does not own — and can steerfirstIndexAfterSelectionand indicator ownership by claiming a selection in an earlier frame. - Reporter/recipient mismatch.
indexInProcesscomes from the reporting process, but follow-up IPC goes to whichever process the UI frame tree says owns the frame; when those differ, a local index lands in another process whoseFindControlleronly guardsmatchIndex >= m_findMatches.size(). - Stale tables.
collectMatchesInFrameTreeOrdersilently drops frames missing from the UI tree, and the table is replaced only when the aggregator is destroyed; check overlapping finds, process crashes, navigations mid-find, dropped replies on process death, and whether the UI fan-out can leave zero or two indicators. - WebContent-side traversal.
Page::findTextMatcheswalksresult.rangeswithtreeOrder<ComposedTree>and dereferencesfirstRange(); check the backwards index arithmetic and shadow-tree ranges, and theframeID()call onrange.start.document().frame()inFindController::findStringMatcheswithout a visible null check.