content/browser/fenced_frame/README.md
Fenced frames are a new HTML element that allows a page to be embedded in another page while preventing any information from being exchanged between the two pages. To maintain this “fence” between a fenced frame and its embedder, any new features need to consider how they should behave inside a fenced frame. Specifically, should they treat the fenced frame as the top-most frame? Or should the feature be allowed to traverse past the fenced frame to get information about its embedder?
The decision chart below is a basic guide to determine how a fenced frame should behave when using a feature:
Below are more details for each node:
Some features need to interact with either a frame’s immediate ancestor, the nearest main frame in the frame tree, or the outermost main frame in the frame tree.
window.top needs to get access to the nearest main frame in the frame tree
(the top-most frame as far as the context is concerned). Even though the
behavior will be different than if it were to get the outermost main frame,
it does not fundamentally break the functionality of this feature.If your feature only needs the immediate ancestor or the nearest main frame, then fenced frames should act as a main frame with your feature..
If you determine that your feature needs a fenced frame to access the outer frame tree (i.e. act as an iframe), you must ensure that no information can leak across the fenced boundary. If any information can leak across the boundary, the feature must be disabled. If the feature cannot be completely disabled, a new approach might need to be formulated (e.g. the ongoing work regarding intersection observer API).
As a direct result of your feature, would you be able to write some JavaScript code whose output changes based on the information your feature knows about ancestors in the embedder frame tree? If you decide that your feature needs to give a fenced frame access to information about its ancestors, this next check is very important. You should ensure that the information gathered from an outer frame tree does not end up in a place where it can be observed on the web platform (i.e. through JavaScript). If it is possible for information to cross the fenced frame boundary in a web-observable way, and there’s no way to patch it, the feature must be disabled in fenced frames.
If you can guarantee that your information is k-anonymized through something like FLEDGE, or scrubbed via something like link decoration mitigation, even though information is flowing across the fenced frame boundary, it might be anonymized enough to allow the feature.
Unless the feature needs access to something outside of a fenced frame, this is how fenced frames will most likely act with your feature. This means that the feature will think that the fenced frame root is the root of the entire frame tree. This also means that accidentally leaking data across the fenced frame boundary is a lot less likely.
This is accomplished by calling helper functions like
RenderFrameHostImpl::GetParent() and RenderFrameHostImpl::GetMainFrame().
RenderFrameHostImpl::SetWindowRect, there’s a check to make sure the
call came from the outermost document. Because fenced frames are meant to
create a boundary and be their own root frame, having the fenced frame act
as a main frame is the correct behavior here. It does not need to know
that there is another frame above it, since it should be acting as if it
were its own separate tab.window.top JavaScript call, if it could reach beyond the fenced frame
root, could allow the fenced frame to learn about its embedder. Having
window.top stop at the fenced frame root will not completely break the
feature, since it will just be acting as if the fenced frame were its own
separate tab. Because of that, the fenced frame should act as the main
frame for this call.
window.parent,
window.postMessage, and history.length.This feature will be made aware of frames above the fenced frame root, and know that there is an outermost root that is not within the fenced frame tree. This path requires extra care, since it becomes possible to have a corner case accidentally leak data across the fenced frame boundary.
This is accomplished by calling helper functions like
RenderFrameHostImpl::GetParentOrOuterDocument() and
RenderFrameHostImpl::GetOutermostMainFrame().
If a feature needs to know about something outside of a fenced frame to function properly, but it’s impossible to expose that information without introducing a leak, the only option is to disallow the feature inside a fenced frame entirely.
There are 2 instances where you will need to write tests to ensure your feature works as expected with fenced frames:
window.top works inside a fenced frame, but it just
returns the fenced frame root. To ensure that this is working
correctly and not actually returning the outermost main frame, there
should be a test confirming this
behavior.There is already infrastructure set up to help you write fenced frames tests.
RenderFrameHostTester class has an
AppendFencedFrame
function. However, double check the file you’re adding a test to, since it
might already have helper functions in its testing
class
to create fenced frames.