From 86578bcf5812ac4ef8c85a704df85bb87c67bf6a Mon Sep 17 00:00:00 2001 From: James Graham Date: Tue, 27 Jul 2021 16:10:08 +0100 Subject: [PATCH 1/2] RFC for context uuids in testdriver --- rfcs/context_uuid.md | 114 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 rfcs/context_uuid.md diff --git a/rfcs/context_uuid.md b/rfcs/context_uuid.md new file mode 100644 index 00000000..45db0078 --- /dev/null +++ b/rfcs/context_uuid.md @@ -0,0 +1,114 @@ +# RFC 87: `testdriver` Extend the mechanisms for giving browsing contexts ids. + +## Summary + +Allow contexts to be identified using either a `testdriver_id` +property on the (window) global, or a `uuid` query parameter, either +on the container `src` attribute (for nested browsing contexts) or the +actual resource URL. + +## Details + +When interacting with either browsing contexts or scripting realms +(hereafter: contexts) other than the test window, it's necessary to +have an identifier for the context that's available both on the js +side and can also be used by WebDriver to identify the context in +question. + +Because of the limitations of the WebDriver-based testdriver setup, we +don't have an existing UUID for each context which could be reused for +this purpose. Instead the `testdriver-extra.js` file in wptrunner +has a `get_window_id` function that takes a `WindowProxy` object, +looks for a `__wptrunner_id` property, if not present sets it to a new +UUID, and then returns the value. Then on the wptrunner side, we use +WebDriver to search the tree of open contexts, executing script in +each one to find the window with that property set. + +This setup works OK for cases where the cross-origin policy allows +setting the property. We also support the case where the non-test +window includes testdriver.js and can postMessage a request to the +top-level window to initiate an action; with some work this allows +supporting any case where it's possible to get a js handle between the +test window and the top-level window. However we have no support for +noopener cases or COOP headers, or other cases where it's not possible +to pass messages between windows using js alone. + +To address these use cases, we propose allowing the use of a `uuid` +query parameter on URLs, which will provide an alternate identifier +for the window that loads the URL. + +In addition we propose updating the `__wptrunner_id` property name to +`testdriver_id`, and making it a documented part of the harness +setup. This will allow the default implementation of testdriver.js to +refer to the property directly rather than it being part of the +wptrunner implementation. + +testdriver will get a new function `get_context_id(ctx)`, with the +following behaviour: +* If `ctx` is a string, return `ctx`. +* If ctx is a WindowProxy with a readable `location.href` which parses + as a URL and has a `uuid` query parameter, return the UUID parameter. +* If ctx is a WindowProxy and it has a `testdriver_id` attribute, + return the value of the attribute, or if it doesn't have such an + attribute, but the Window is writable from the current context, set + `testdriver_id` to a new id and return that. +* If `ctx` is a nested browsing context container with a `src` + attribute (for `iframe`, `frame`, `embed`) or `data` attribute (for + `object`) and the attribute value parses as a URL with a uuid + query parameter, return the uuid parameter. + +On the wptrunner side, we keep the same behaviour of searching through +the tree of browsing contexts, but in addition we parse `uuid` query +strings out of the attribute values of nested context containers and +the URLs of loaded documents, and match those against the target URL. + +In this system a specific context may have more than one associated id +(if the various ways of setting it differ), but we can use any +associated id to get to the browsing context. + +For noopener cases, we can now provide a uuid in the URL and use that +to invoke testdriver actions on the remote context: + +``` +// Use the server subn to generate a UUID +let uuid = "{{uuid()}}" +open(`child.html?uuid={uuid}`) +// [...] stuff to ensure child is loaded etc. +// In this case the context identifier is used directly +test_driver.delete_all_cookies(uuid) +``` + +We can also access a cross-origin-nested context: +``` + + ``` TODO: How should this extend to other resources such as worker scripts. For