Fenced frames: add browser-side focus verification.

Fenced frames have checks to make sure that focus cannot be pulled
programmatically across a fenced frame boundary. However, because of how
user activation works, all of the gating happens on the renderer side.
This is problematic because this allows a compromised renderer to pull
focus across a fenced frame boundary as much as it wants, which can be
used to open a communication channel.

This CL adds checks on the browser side to make sure that any renderer
that pulls focus across a fenced frame boundary was allowed to do so.
This handles every focus case, including tab traversals, clicking to
focus, programmatic focus, and accessibility-based focusing. If the
browser determines focus was not allowed, the plan is to consider the
renderer compromised and kill it. Right now, until we know for sure that
there are no false positives with this check, we will instead call
DumpWithoutCrashing() to be able to monitor this.

Note that the focus check will bad message the renderer in tests, CQ,
and ToT builds.

This CL introduces a new transient state tracking mechanism that will
track if a RFHI passing focus had transient user activation. As focus is
moved from one RFHI to the next (through the
RenderFrameProxyHost::AdvanceFocus and RenderFrameHostImpl::TakeFocus
calls), the transient user activation status will be passed with the
focus change.

A new transient state tracking mechanism is added to
RenderWidgetHostImpl to track if focus was lost between calls to
RenderFrameHostImpl::DidFocusFrame(). This is done in order to detect if
focus was moved from a page to a UI element (such as the navbar). This
is needed because focus moving from a UI element back to the page could
be considered a bad focus otherwise.

The logic that consumes user activation when crossing a fenced frame
boundary is moved from the renderer to the browser as part of this
change, since focus verification needs to complete before user
activation can be consumed.

Examples:

MainFrame(FF1):
- If the main frame currently has focus and we click on FF1, the focus
checks will succeed simply because the click action gave the fenced
frame user activation.
- If instead we <tab> focus from MainFrame to FF1, the focus transfer
into FF1 will succeed specifically because <tab> gives MainFrame user
activation (which allows it to transfer focus). FF1 script will observe
the focus transfer into it, but user activation will not come with it.
- If we move focus from FF1 to another element in FF1, focus will be
allowed because the change in focus does not cross into a fenced frame
boundary.
- If a compromised renderer tries to move focus from MainFrame to FF1
without user gesture, since there is no user gesture on either frames,
and since focus is crossing a fenced frame boundary, the browser will
reject the focus change and badmessage the renderer. Note that this CL
will only badmessage the renderer in tests, CQ, and ToT builds. All
other builds will instead call DumpWithoutCrashing() so we can monitor
potential missed corner cases.

MainFrame(FF1(FF2),FF3) with a focusable element only in MainFrame and
FF3:
- If we <tab> focus through the focusable elements, we will first focus
on the element in MainFrame. Focus is allowed because it is not crossing
a fenced frame boundary into a fenced frame. The MainFrame will also get
transient user activation as a result of this action. We then wait for
MainFrame's transient user activation to expire before performing the
next step.
- The next <tab> gets more complicated. MainFrame will get transient
user activation, and then (1) activate FF1's transient state, (2)
deactivate MainFrame's transient state, and (3) pass focus into FF1.
This passing of focus into FF1 is allowed because the transient state
has been activated as a part of the user-gesture-initiated focus from
MainFrame => FF1. However, there are no focusable elements in FF1 so,
through RenderFrameProxyHost::AdvanceFocus(), FF1 will (1) activate
FF2's transient state, (2) deactivate FF1's transient state, and (3)
pass focus to FF2.
- Focus is allowed in FF2 due to the transient state, but FF2 still
needs to pass focus to the next frame. Through
RenderFrameHostImpl::TakeFocus(), FF2 will (1) activate FF1's transient
state, (2) deactivate FF2's transient state, and (3) pass focus back up
to FF1. FF1 will perform the same actions with MainFrame, which in turn
will perform the same actions with FF3 through
RenderFrameProxyHost::AdvanceFocus().
- FF3 has an element it can focus, so FF3 will focus that element, and
the focus check will pass because its transient state is activated.

MainFrame(FF1(FF2),FF3) with a focusable element only in FF3:
- If we press <tab> for the first time, MainFrame will get user
activation as we start the same traversal process as outlined in the
previous example. We will end up with the element in FF3 getting focus.
- If we press <tab> again, focus will leave the RenderWidgetHost and go
into the UI. RenderWidgetHostImpl::LostFocus() will be called and it
will set `has_lost_focus_` to true.
- Pressing <tab> one more time will start the traversal process again.
However, this time, no frames will have user activation. Instead,
MainFrame will see that `has_lost_focus_` is true, and will activate its
transient state tracking mechanism due to that. It will then go through
the same traversal process, where this time the transient state tracking
mechanism will be active due to the RWH losing focus rather than the
focus originator having user activation.

See design document: https://docs.google.com/document/d/1DH9l2mQJbPBJkSEkyVQPpswLafEwSPvKybMJRfgNuhA/edit?usp=sharing

Change-Id: I4c771ac56605f204ef3facb501115ff8ce01b428
Bug: 1458985
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4572517
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Peter Beverloo <peter@chromium.org>
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Commit-Queue: Liam Brady <lbrady@google.com>
Reviewed-by: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1184289}
1 file changed
tree: 85ae3339d7101d5b7b9d155ee096b3f742d6ce92
  1. .github/
  2. .well-known/
  3. accelerometer/
  4. accessibility/
  5. accname/
  6. acid/
  7. ambient-light/
  8. animation-worklet/
  9. annotation-model/
  10. annotation-protocol/
  11. annotation-vocab/
  12. apng/
  13. appmanifest/
  14. attribution-reporting/
  15. audio-output/
  16. autoplay-policy-detection/
  17. avif/
  18. background-fetch/
  19. background-sync/
  20. badging/
  21. battery-status/
  22. beacon/
  23. bluetooth/
  24. browsing-topics/
  25. captured-mouse-events/
  26. clear-site-data/
  27. client-hints/
  28. clipboard-apis/
  29. close-watcher/
  30. common/
  31. compat/
  32. compression/
  33. compute-pressure/
  34. conformance-checkers/
  35. console/
  36. contacts/
  37. content-dpr/
  38. content-index/
  39. content-security-policy/
  40. contenteditable/
  41. cookie-store/
  42. cookies/
  43. core-aam/
  44. cors/
  45. credential-management/
  46. css/
  47. custom-elements/
  48. custom-state-pseudo-class/
  49. delegated-ink/
  50. density-size-correction/
  51. deprecation-reporting/
  52. device-memory/
  53. direct-sockets/
  54. docs/
  55. document-picture-in-picture/
  56. document-policy/
  57. dom/
  58. domparsing/
  59. domxpath/
  60. dpub-aam/
  61. dpub-aria/
  62. ecmascript/
  63. editing/
  64. element-timing/
  65. encoding/
  66. encoding-detection/
  67. encrypted-media/
  68. entries-api/
  69. event-timing/
  70. eventsource/
  71. eyedropper/
  72. feature-policy/
  73. fenced-frame/
  74. fetch/
  75. file-system-access/
  76. FileAPI/
  77. fledge/
  78. focus/
  79. font-access/
  80. fonts/
  81. forced-colors-mode/
  82. fs/
  83. fullscreen/
  84. gamepad/
  85. generic-sensor/
  86. geolocation-API/
  87. geolocation-sensor/
  88. graphics-aam/
  89. graphics-aria/
  90. gyroscope/
  91. hr-time/
  92. html/
  93. html-aam/
  94. html-longdesc/
  95. html-media-capture/
  96. https-upgrades/
  97. idle-detection/
  98. imagebitmap-renderingcontext/
  99. images/
  100. import-maps/
  101. IndexedDB/
  102. inert/
  103. infrastructure/
  104. input-device-capabilities/
  105. input-events/
  106. installedapp/
  107. interfaces/
  108. intersection-observer/
  109. intervention-reporting/
  110. is-input-pending/
  111. js/
  112. js-self-profiling/
  113. keyboard-lock/
  114. keyboard-map/
  115. largest-contentful-paint/
  116. layout-instability/
  117. lifecycle/
  118. loading/
  119. long-animation-frame/
  120. longtask-timing/
  121. magnetometer/
  122. managed/
  123. mathml/
  124. measure-memory/
  125. media/
  126. media-capabilities/
  127. media-playback-quality/
  128. media-source/
  129. mediacapture-extensions/
  130. mediacapture-fromelement/
  131. mediacapture-handle/
  132. mediacapture-image/
  133. mediacapture-insertable-streams/
  134. mediacapture-record/
  135. mediacapture-region/
  136. mediacapture-streams/
  137. mediasession/
  138. merchant-validation/
  139. mimesniff/
  140. mixed-content/
  141. mst-content-hint/
  142. navigation-api/
  143. navigation-timing/
  144. netinfo/
  145. network-error-logging/
  146. notifications/
  147. old-tests/
  148. orientation-event/
  149. orientation-sensor/
  150. page-lifecycle/
  151. page-visibility/
  152. paint-timing/
  153. parakeet/
  154. payment-handler/
  155. payment-method-basic-card/
  156. payment-method-id/
  157. payment-request/
  158. pending-beacon/
  159. performance-timeline/
  160. periodic-background-sync/
  161. permissions/
  162. permissions-policy/
  163. permissions-request/
  164. permissions-revoke/
  165. picture-in-picture/
  166. png/
  167. pointerevents/
  168. pointerlock/
  169. portals/
  170. preload/
  171. presentation-api/
  172. private-aggregation/
  173. private-click-measurement/
  174. proximity/
  175. push-api/
  176. quirks/
  177. referrer-policy/
  178. remote-playback/
  179. reporting/
  180. requestidlecallback/
  181. resize-observer/
  182. resource-timing/
  183. resources/
  184. sanitizer-api/
  185. savedata/
  186. scheduler/
  187. screen-capture/
  188. screen-details/
  189. screen-orientation/
  190. screen-wake-lock/
  191. scroll-animations/
  192. scroll-to-text-fragment/
  193. secure-contexts/
  194. secure-payment-confirmation/
  195. selection/
  196. serial/
  197. server-timing/
  198. service-workers/
  199. shadow-dom/
  200. shape-detection/
  201. shared-storage/
  202. shared-storage-selecturl-limit/
  203. signed-exchange/
  204. soft-navigation-heuristics/
  205. speculation-rules/
  206. speech-api/
  207. storage/
  208. storage-access-api/
  209. streams/
  210. subapps/
  211. subresource-integrity/
  212. svg/
  213. svg-aam/
  214. timing-entrytypes-registry/
  215. tools/
  216. top-level-storage-access-api/
  217. touch-events/
  218. trust-tokens/
  219. trusted-types/
  220. ua-client-hints/
  221. uievents/
  222. upgrade-insecure-requests/
  223. url/
  224. urlpattern/
  225. user-timing/
  226. vibration/
  227. video-rvfc/
  228. virtual-keyboard/
  229. visual-viewport/
  230. wai-aria/
  231. wasm/
  232. web-animations/
  233. web-bundle/
  234. web-locks/
  235. web-nfc/
  236. web-otp/
  237. web-share/
  238. webaudio/
  239. webauthn/
  240. webcodecs/
  241. WebCryptoAPI/
  242. webdriver/
  243. webgl/
  244. webgpu/
  245. webhid/
  246. webidl/
  247. webmessaging/
  248. webmidi/
  249. webnn/
  250. webrtc/
  251. webrtc-encoded-transform/
  252. webrtc-extensions/
  253. webrtc-ice/
  254. webrtc-identity/
  255. webrtc-priority/
  256. webrtc-stats/
  257. webrtc-svc/
  258. websockets/
  259. webstorage/
  260. webtransport/
  261. webusb/
  262. webvr/
  263. webvtt/
  264. webxr/
  265. window-management/
  266. workers/
  267. worklets/
  268. x-frame-options/
  269. xhr/
  270. .azure-pipelines.yml
  271. .gitattributes
  272. .gitignore
  273. .mailmap
  274. .taskcluster.yml
  275. CODE_OF_CONDUCT.md
  276. CODEOWNERS
  277. CONTRIBUTING.md
  278. LICENSE.md
  279. lint.ignore
  280. README.md
  281. wpt
  282. wpt.py
README.md

The web-platform-tests Project

Taskcluster CI Status documentation manifest Python 3

The web-platform-tests Project is a cross-browser test suite for the Web-platform stack. Writing tests in a way that allows them to be run in all browsers gives browser projects confidence that they are shipping software that is compatible with other implementations, and that later implementations will be compatible with their implementations. This in turn gives Web authors/developers confidence that they can actually rely on the Web platform to deliver on the promise of working across browsers and devices without needing extra layers of abstraction to paper over the gaps left by specification editors and implementors.

The most important sources of information and activity are:

  • github.com/web-platform-tests/wpt: the canonical location of the project's source code revision history and the discussion forum for changes to the code
  • web-platform-tests.org: the documentation website; details how to set up the project, how to write tests, how to give and receive peer review, how to serve as an administrator, and more
  • wpt.live: a public deployment of the test suite, allowing anyone to run the tests by visiting from an Internet-enabled browser of their choice
  • wpt.fyi: an archive of test results collected from an array of web browsers on a regular basis
  • Real-time chat room: the wpt:matrix.org matrix channel; includes participants located around the world, but busiest during the European working day.
  • Mailing list: a public and low-traffic discussion list
  • RFCs: a repo for requesting comments on substantial changes that would impact other stakeholders or users; people who work on WPT infra are encouraged to watch the repo.

If you'd like clarification about anything, don't hesitate to ask in the chat room or on the mailing list.

Setting Up the Repo

Clone or otherwise get https://github.com/web-platform-tests/wpt.

Note: because of the frequent creation and deletion of branches in this repo, it is recommended to “prune” stale branches when fetching updates, i.e. use git pull --prune (or git fetch -p && git merge).

Running the Tests

See the documentation website and in particular the system setup for running tests locally.

Command Line Tools

The wpt command provides a frontend to a variety of tools for working with and running web-platform-tests. Some of the most useful commands are:

  • wpt serve - For starting the wpt http server
  • wpt run - For running tests in a browser
  • wpt lint - For running the lint against all tests
  • wpt manifest - For updating or generating a MANIFEST.json test manifest
  • wpt install - For installing the latest release of a browser or webdriver server on the local machine.
  • wpt serve-wave - For starting the wpt http server and the WAVE test runner. For more details on how to use the WAVE test runner see the documentation.

Windows Notes

On Windows wpt commands must be prefixed with python or the path to the python binary (if python is not in your %PATH%).

python wpt [command]

Alternatively, you may also use Bash on Ubuntu on Windows in the Windows 10 Anniversary Update build, then access your windows partition from there to launch wpt commands.

Please make sure git and your text editor do not automatically convert line endings, as it will cause lint errors. For git, please set git config core.autocrlf false in your working tree.

Publication

The master branch is automatically synced to wpt.live and w3c-test.org.

Contributing

Save the Web, Write Some Tests!

Absolutely everyone is welcome to contribute to test development. No test is too small or too simple, especially if it corresponds to something for which you've noted an interoperability bug in a browser.

The way to contribute is just as usual:

  • Fork this repository (and make sure you're still relatively in sync with it if you forked a while ago).
  • Create a branch for your changes: git checkout -b topic.
  • Make your changes.
  • Run ./wpt lint as described above.
  • Commit locally and push that to your repo.
  • Create a pull request based on the above.

Issues with web-platform-tests

If you spot an issue with a test and are not comfortable providing a pull request per above to fix it, please file a new issue. Thank you!