From c375277585a5a4862b7b83b4070472c08c242dbc Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Tue, 29 Jan 2019 14:52:10 +0100 Subject: [PATCH] Refactor browsing context creation Some initial work to make introducing browsing context groups (see #4198) easier. Fixes #2636 by making opener browsing context more generally applicable and making window.open() set it. Fixes #2645 by removing creator browsing context and explicitly passing in the creator document. Tests: https://github.com/web-platform-tests/wpt/pull/15078. --- source | 455 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 250 insertions(+), 205 deletions(-) diff --git a/source b/source index 1a28076a92f..15ab2b6d64d 100644 --- a/source +++ b/source @@ -6799,7 +6799,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

If document's URL is about:blank, and document's browsing - context has a creator browsing context, then return the creator base + context's creator base URL is non-null, then return that creator base URL.

@@ -23242,9 +23242,6 @@ document.body.appendChild(wbr);
  • If target is null, then return.

  • -
  • If noopener and replace are true, then disown target.

  • -
  • Parse the URL given by subject's href attribute, relative to subject's node document.

  • @@ -23794,8 +23791,9 @@ document.body.appendChild(wbr); not allowed Annotation · - Indicates that any browsing context created by following the hyperlink is - disowned. + Creates a top-level browsing context that is not an auxiliary + browsing context if the hyperlink would create either of those to begin with (i.e., has + an appropriate target attribute value). @@ -23803,9 +23801,8 @@ document.body.appendChild(wbr); not allowed Annotation · - Indicates that any browsing context created by following the hyperlink is - disowned and will not get a `Referer` (sic) - header. + No `Referer` (sic) header will be included. + Additionally, has the same effect as noopener. @@ -24557,9 +24554,32 @@ document.body.appendChild(wbr); data-x="hyperlink annotation">annotates any other hyperlinks created by the element (the implied hyperlink, if no other keywords create one).

    -

    The keyword indicates that any newly created browsing context which results from - following the hyperlink will be disowned, which means that its window.opener attribute will be null.

    +

    The keyword indicates that any newly created top-level browsing context which + results from following the hyperlink will not be an auxiliary browsing + context. E.g., its window.opener attribute will be + null.

    + +

    See also the processing model where the branching between + an auxiliary browsing context and a top-level browsing context is + defined.

    + +
    +

    This typically creates an auxiliary browsing context (assuming there is no + existing browsing context whose browsing context name is + "example"):

    + +
    <a href=help.html target=example>Help!</a>
    + +

    This creates a top-level browsing context that is not an auxiliary browsing + context (assuming the same thing):

    + +
    <a href=help.html target=example rel=noopener>Help!</a>
    + +

    These are equivalent and only navigate the parent browsing context:

    + +
    <a href=index.html target=_parent>Home</a>
    +
    <a href=index.html target=_parent rel=noopener>Home</a>
    +
    Link type "noreferrer"
    @@ -29787,12 +29807,23 @@ interface HTMLIFrameElement : HTMLElement {
    -

    When an iframe element is inserted - into a document that has a browsing context, the - user agent must create a new browsing - context, set the element's nested browsing context to the newly-created - browsing context, and then process the iframe attributes - for the "first time".

    +

    When an iframe element element is inserted into a document that has a browsing + context, the user agent must run these steps: + +

      +
    1. Let browsingContext be the result of creating a new browsing + context with element's node document.

    2. + +
    3. Set the element's nested browsing context to + browsingContext.

    4. + +
    5. If element has a name attribute, then + set browsingContext's name to the value of + this attribute.

    6. + +
    7. Process the iframe attributes for the "first time".

    8. +

    When an iframe element is removed from a document, the user agent must name attribute, if present, must be a valid browsing context name. The given value is used to name the nested - browsing context. When the browsing context is created, if the attribute - is present, the browsing context name must be set to the value of this attribute; - otherwise, the browsing context name must be set to the empty string.

    + browsing context.

    @@ -30531,13 +30560,15 @@ interface HTMLEmbedElement : HTMLElement {

    If element's nested browsing context is null, then:

      -
    1. Set element's nested browsing context to a newly-created browsing - context.

    2. +
    3. Let browsingContext be the result of creating a new browsing + context with element's node document.

    4. + +
    5. Set element's nested browsing context to + browsingContext.

    6. If element has a name - attribute, then set the browsing context name of element's new - nested browsing context to the value of this attribute.

    7. + attribute, then set browsingContext's name to the value of this attribute.

    @@ -31318,7 +31349,8 @@ interface HTMLObjectElement : HTMLElement {

    If the object element's nested browsing context is null, set the element's nested browsing context to a newly-created browsing context.

    + browsing context">newly-created browsing context with the element's node + document.

    The object element must be associated with a newly created nested browsing context, if it does not already have one.

    @@ -76952,6 +76984,12 @@ dictionary DragEventInit : MouseEventInit {

    A browsing context has a corresponding WindowProxy object.

    +

    A browsing context has an opener browsing context, which + is null or a browsing context. It is initially null.

    + +

    A browsing context has a disowned boolean. It + is initially false.

    +

    A browsing context has a session history, which lists the Document objects that the browsing context has presented, is presenting, or will present. A browsing context's active document is @@ -76981,6 +77019,10 @@ dictionary DragEventInit : MouseEventInit { browsing context, since that browsing context was discarded.

    + + +

    Creating browsing contexts

    +

    To set the active document of a browsing context browsingContext to a Document object document, run these steps:

    @@ -77007,43 +77049,28 @@ dictionary DragEventInit : MouseEventInit {
    -

    A browsing context can have a creator browsing context, - the browsing context that was responsible for its creation. If a browsing - context has a parent browsing context, then that is its creator browsing - context. Otherwise, if the browsing context has an opener browsing - context, then that is its creator browsing context. Otherwise, the - browsing context has no creator browsing context.

    - -

    If a browsing context context has a creator browsing - context creator, it also has the following properties. In what follows, let - creator document be creator's active document at the time - context is created:

    - -
    -
    creator origin
    -
    creator document's origin
    - -
    creator URL
    -
    creator document's URL
    - -
    creator base URL
    -
    creator document's base URL
    - -
    creator referrer policy
    -
    creator document's referrer - policy
    -
    +

    A browsing context has an associated creator origin (null or returns an + origin), creator URL (null or returns a URL), creator + base URL (null or returns a URL), and creator referrer policy (null + or returns a referrer policy). These are all initially null.

    -

    To create a new browsing context, - optionally given noopener:

    +

    To create a new browsing context, given + null or a Document object creator:

      -
    1. If noopener was not given, let it be false.

    2. -
    3. Let browsingContext be a new browsing context.

    4. +
    5. If creator is non-null, then set + browsingContext's creator origin to return creator's + origin, browsingContext's creator URL to return + creator's URL, browsingContext's + creator base URL to return creator's base URL, and browsingContext's creator referrer policy to + return creator's referrer + policy.

    6. +
    7. Let realm execution context be the result of creating a new JavaScript realm with the following customizations:

      @@ -77071,25 +77098,19 @@ dictionary DragEventInit : MouseEventInit {
    8. Set the active document of browsingContext to document.

    9. -
    10. -

      Set the origin of document:

      +
    11. If browsingContext's creator origin is + non-null, then set document's origin to it.

    12. -
        -
      • If browsingContext has a creator browsing context, then the - origin of document is the creator origin.

      • +
      • Otherwise, set document's origin to a unique opaque origin.

      • -
      • Otherwise, the origin of document is a unique opaque origin.

      • -
      - - -
    13. If browsingContext has a creator browsing context, then set +

    14. If browsingContext's creator URL is non-null, then set document's referrer to the serialization of creator URL.

    15. + data-x="concept-url-serializer">serialization of it.

      -
    16. If browsingContext has a creator browsing context, then set +

    17. If browsingContext's creator referrer policy is non-null, then set document's referrer policy to - the creator referrer policy.

    18. + it.

    19. Implement the sandboxing for document.

    20. @@ -77099,26 +77120,50 @@ dictionary DragEventInit : MouseEventInit {
    21. Add document to browsingContext's session history.

    22. +
    23. Return browsingContext.

    24. +
    + +

    To create a new top-level browsing + context:

    + +
      +
    1. Return the result of creating a new browsing context with null.

    2. +
    + +

    This creates a top-level browsing context.

    + +

    To create a new auxiliary browsing + context, given a browsing context opener: + +

      +
    1. Let browsingContext be the result of creating a new browsing + context with opener's active document.

    2. + +
    3. Set browsingContext's opener browsing context to + opener.

    4. + +
    5. Assert: browsingContext's creator origin is non-null.

    6. + +
    7. If browsingContext's creator origin is + same origin with browsingContext's active document's + origin, then copy the sessionStorage + storage area of opener into browsingContext's set of session storage areas. + These areas must be considered separate, not affecting each other in any way.

    8. -
    9. If noopener is false, browsingContext is a - top-level browsing context, and creator origin is same - origin with document's origin, then copy the sessionStorage storage area of the creator origin - from the creator browsing context into browsingContext's set of session - storage areas. These areas must be considered separate, not affecting each other in any - way.

    10. -
    11. Return browsingContext.

    +

    This creates a top-level browsing context that is also an + auxiliary browsing context.

    +
    -

    Nested browsing contexts

    +

    Related browsing contexts

    Certain elements (for example, iframe elements) can instantiate further browsing contexts. These elements are called DragEventInit : MouseEventInit { context">ancestor of B, or if the browsing context A is the parent browsing context of B.

    -

    A browsing context that is not a nested browsing context has no - parent browsing context, and is the top-level browsing - context of all the browsing contexts for which it is an ancestor browsing - context.

    +

    A browsing context that has no parent browsing context is the top-level browsing context for itself and all of the browsing contexts for + which it is an ancestor browsing context.

    + +

    It is possible to create new browsing contexts that are related to a top-level browsing + context without being nested through an element. Such browsing contexts are called auxiliary + browsing contexts. Auxiliary browsing contexts are always top-level browsing contexts.

    The transitive closure of parent browsing contexts for a browsing context that is a nested browsing context gives the list @@ -77316,34 +77366,34 @@ dictionary DragEventInit : MouseEventInit { -

    Navigating nested browsing contexts in the DOM
    +
    -
    window . top
    +
    +

    Returns the WindowProxy for the top-level browsing context.

    +
    +
    window . opener [ = value ]
    +

    Returns the WindowProxy for the opener browsing context.

    -

    Returns the WindowProxy for the top-level browsing context.

    +

    Returns null if there isn't one or if it has been set to null.

    +

    Can be set to null.

    window . parent
    -
    -

    Returns the WindowProxy for the parent browsing context.

    -
    window . frameElement
    -
    -

    Returns the Element for the browsing context container.

    Returns null if there isn't one, and in cross-origin situations.

    -
    @@ -77370,6 +77420,46 @@ dictionary DragEventInit : MouseEventInit { top-level browsing context's WindowProxy object.

    +

    The opener attribute's getter must run these + steps:

    + +
      +
    1. If the current browsing context's disowned is true, then return + null.

    2. + +
    3. If the current browsing context's opener browsing context is + null, then return null.

    4. + +
    5. Return the current browsing context's opener browsing context's + WindowProxy object.

    6. +
    + +

    The opener attribute's setter, must run these steps:

    + +
      +
    1. If the given value is null, then set the current browsing context's + disowned to true and return.

    2. + +
    3. Return ? OrdinaryDefineOwnProperty(this Window object, "opener", { [[Value]]: the given value, [[Writable]]: true, [[Enumerable]]: true, + [[Configurable]]: true }).

    4. +
    + +
    +

    If a browsing context's disowned is true, its window.opener attribute is null. That prevents scripts in the + browsing context from changing any properties of its opener browsing + context's Window object (i.e., the Window object from which the + browsing context was created).

    + +

    Otherwise, if a browsing context's disowned is false, then scripts + in that browsing context can use window.opener to + change properties of its opener browsing context's Window object. For + example, a script running in the browsing context can change the value of window.opener.location, causing the opener browsing context to + navigate to a completely different document.

    +
    +

    The parent IDL attribute, on getting, must run the following algorithm:

    @@ -77437,72 +77527,7 @@ console.assert(iframeWindow.frameElement === null); data-x="">element was removed from the document.

    - - - - -

    Auxiliary browsing contexts

    - -

    It is possible to create new browsing contexts that are related to a top-level browsing - context without being nested through an element. Such browsing contexts are called auxiliary - browsing contexts. Auxiliary browsing contexts are always top-level browsing - contexts.

    - -

    An auxiliary browsing context has an opener browsing - context, which is the browsing context from which the auxiliary browsing - context was created.

    - - -
    Navigating auxiliary browsing contexts in the DOM
    - -

    An auxiliary browsing context can be disowned.

    - -

    The opener attribute's getter must run these - steps:

    - -
      -
    1. If the current browsing context is disowned, then return - null.

    2. - -
    3. If the current browsing context has no opener browsing context, - then return null.

    4. - -
    5. Return the current browsing context's opener browsing context's - WindowProxy object.

    6. -
    -

    The opener attribute's setter, must run these steps:

    - -
      -
    1. If the given value is null, then disown the current - browsing context and return.

    2. - -
    3. Perform OrdinaryDefineOwnProperty(this Window object, "opener", { [[Value]]: the given value, [[Writable]]: true, [[Enumerable]]: true, - [[Configurable]]: true }). Rethrow any exceptions.

    4. -
    - -
    -

    If a browsing context is disowned, its window.opener attribute is null. That prevents scripts in the - browsing context from changing any properties of its opener browsing - context's Window object (i.e., the Window object from which the - browsing context was created).

    - -

    Otherwise, if a browsing context is not disowned, then scripts in - that browsing context can use window.opener to - change properties of its opener browsing context's Window object. For - example, a script running in the browsing context can change the value of window.opener.location, causing the opener browsing context to - navigate to a completely different document.

    -
    - - - -

    Security

    @@ -77798,6 +77823,9 @@ console.assert(iframeWindow.frameElement === null);
  • Let new be false.

  • +
  • Let sandboxingFlagSet be current's active document's + active sandboxing flag set.

  • +
  • If name is the empty string or an ASCII case-insensitive match for "_self", then set chosen to current.

  • @@ -77835,17 +77863,15 @@ console.assert(iframeWindow.frameElement === null);

    The user agent may inform the user that a popup has been blocked.

    -
    If current's active document's active - sandboxing flag set has the sandboxed auxiliary navigation browsing context - flag set
    +
    If sandboxingFlagSet has the sandboxed auxiliary + navigation browsing context flag set

    The user agent may offer the user one of:

      -
    1. Set chosen to a new - top-level browsing context given noopener, and set new to - true.

    2. +
    3. Set chosen to the result of creating a new top-level browsing + context and set new to true.

    4. Set chosen to an existing top-level browsing context.

    @@ -77857,16 +77883,37 @@ console.assert(iframeWindow.frameElement === null); remain unchanged.

    -
    If the user agent has been configured such that in this instance it will - create a new browsing context
    +
    If the user agent has been configured such that in this instance it will create a new + browsing context
    -

    Set chosen to a new - auxiliary browsing context given noopener with the opener - browsing context being current, and set new to true. If - name is not an ASCII case-insensitive match for "_blank", then chosen's name must be set to name.

    +
      +
    1. Set new to true.

    2. + +
    3. If noopener is true, then set chosen to the result + of creating a new top-level browsing context.

    4. + +
    5. +

      Otherwise:

      + +
        +
      1. Set chosen to the result of creating a new auxiliary browsing + context with current.

      2. + +
      3. If sandboxingFlagSet's sandboxed navigation browsing context + flag is set, then current must be set as chosen's one + permitted sandboxed navigator.

      4. +
      +
    6. + +
    7. If sandboxingFlagSet's sandbox propagates to auxiliary browsing + contexts flag is set, then all the flags that are set in sandboxingFlagSet + must be set in chosen's popup sandboxing flag set.

    8. + +
    9. If name is not an ASCII case-insensitive match for "_blank", then set chosen's name to name.

    10. +

    If the newly created browsing context is immediately navigated, then the navigation will be done with replacement @@ -77878,7 +77925,6 @@ console.assert(iframeWindow.frameElement === null);

    Set chosen to current.

    -
    If the user agent has been configured such that in this instance it will not find a browsing context
    @@ -77889,23 +77935,6 @@ console.assert(iframeWindow.frameElement === null); agent to always reuse current.

    -
  • -

    If new is true, then:

    - -
      -
    1. Let flagSet be current's active document's - active sandboxing flag set.

    2. - -
    3. If flagSet's sandboxed navigation browsing context flag is set, - then current must be set as chosen's one permitted sandboxed - navigator.

    4. - -
    5. If flagSet's sandbox propagates to auxiliary browsing contexts - flag is set, then all the flags that are set in flagSet must be set in - chosen's popup sandboxing flag set.

    6. -
    -
  • -
  • Return chosen and new.

  • @@ -78481,8 +78510,15 @@ dictionary WindowPostMessageOptions : PostMessageOptions -
  • If noopener is true, then disown target - browsing context and return null.

  • +
  • If noopener is true, then return null.

  • + +
  • +

    Otherwise, if new is false, set target browsing context's opener + browsing context to source browsing context.

    + +

    If new is true this is done as part of creating a new auxiliary + browsing context.

    +
  • Return target browsing context's WindowProxy object.

  • @@ -89036,9 +89072,9 @@ import "https://example.com/foo/../module2.mjs"; origin-domain with A.
  • Any two Window objects whose browsing - contexts do not have an opener or ancestor relationship. This holds even if the two - Window objects are same origin.
  • + contexts do not have a non-null opener or + ancestor relationship. This holds even if the + two Window objects are same origin.
    @@ -99582,8 +99618,8 @@ interface Storage { area. Each Document object must have a separate object for its relevant global object's sessionStorage attribute.

    -

    While creating a new browsing context, the session storage area is sometimes copied over.

    +

    While creating a new auxiliary browsing context, the session storage area is copied over.

    @@ -115262,14 +115298,23 @@ interface HTMLFrameSetElement : HTMLElement { -

    When a frame element is created as an active frame - element, or becomes an active frame element after not having been - one, the user agent must create a new browsing - context, set the element's nested browsing context to the newly-created - browsing context, and then process the frame attributes for - the first time. If the element has a name - attribute, the browsing context name must be set to the value of this attribute; - otherwise, the browsing context name must be set to the empty string.

    +

    When a frame element element is created as an active + frame element, or becomes an active frame element + after not having been one, the user agent must run these steps:

    + +
      +
    1. Let browsingContext be the result of creating a new browsing + context with element's node document.

    2. + +
    3. Set element's nested browsing context to + browsingContext.

    4. + +
    5. If element has a name + attribute, then set browsingContext's name + to the value of this attribute.

    6. + +
    7. Process the frame attributes for the first time.

    8. +

    When a frame element stops being an active frame element, the user agent must discard