From df0298517e01e07be9c9b4eb7c44dcf603c051c3 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Thu, 29 Feb 2024 16:48:10 +1100 Subject: [PATCH 01/42] Added tabbed to candidate display mode list. --- index.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.html b/index.html index 26cf484..8199152 100644 --- a/index.html +++ b/index.html @@ -92,6 +92,10 @@

mode/window-controls-overlay=] and the user agent supports this, then return that |candidate_display_mode:DisplayModeType|. +
  • If |candidate_display_mode:DisplayModeType| is [=display + mode/tabbed=] and the user agent supports this, then return that + |candidate_display_mode:DisplayModeType|. +
  • From 95849ae9457a5cb72ba040a901d0b85aca60d007 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Thu, 29 Feb 2024 16:52:40 +1100 Subject: [PATCH 02/42] Update note. --- index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 8199152..c1f9b63 100644 --- a/index.html +++ b/index.html @@ -102,8 +102,10 @@

    This member is intended to be only used for advanced cases, where the developer wants explicit control over the fallback order of their - display modes. Otherwise, the [=manifest/display=] member is sufficient - for most use cases. + display modes, or for modes that are not available in the basic + display modes + list. Otherwise, the [=manifest/display=] member is sufficient for + most use cases.

    From a72aa406717be0161f6bc33a28023568d7ea6a25 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Thu, 29 Feb 2024 17:06:52 +1100 Subject: [PATCH 03/42] Added tabbed display mode and tab_strip member. --- index.html | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/index.html b/index.html index c1f9b63..8a6c54d 100644 --- a/index.html +++ b/index.html @@ -145,6 +145,15 @@

    [=display mode/window-controls-overlay=]
    +
    + tabbed +
    +
    + The web application can have multiple application contexts combined + in a single operating-system-level window. For example, this could + mean the user agent displays a tab strip UI to allow the user to + switch between the application contexts. +

    @@ -224,6 +233,24 @@

    +
    +

    + tab_strip member +

    +

    + The `tab_strip` member of the Web Application Manifest is + an object that contains + information about how the application is intended to behave in the + [=display mode/tabbed=] display mode. It has the following members: +

    +
      +
    • [=tab_strip/home_tab=] +
    • +
    • [=tab_strip/new_tab_button=] +
    • +
    +

    `share_target` member From b8a1e95b43810c5cdf3e0f691fe10d9fb56fb9b8 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Thu, 29 Feb 2024 17:30:39 +1100 Subject: [PATCH 04/42] Added full details on the tab_strip member. Copy-pasted from Louise Brett's source doc. Need to clean up, linkify and edit. --- index.html | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/index.html b/index.html index 8a6c54d..e33a8af 100644 --- a/index.html +++ b/index.html @@ -250,6 +250,214 @@

  • [=tab_strip/new_tab_button=]
  • +
    +

    + home_tab member +

    +

    + The home_tab member of the tab_strip object is an ordered map that + contains information about a specially marked application context + that, if it exists, is in every app window. This application context + has special properties compared to other application contexts, such + as restricted navigation and it SHOULD have a different appearance. +

    +

    + A home tab context is the application context in which these special + properties are applied. +

    + +

    + If the home_tab member is not present, then the application is not + intended to have a home tab context, otherwise it is an ordered map + with the following members: +

    +
      +
    • [=home_tab/scope_patterns=] +
    • +
    +

    + How the home tab context is presented is at the discretion of the + user agent. +

    +

    + The home tab scope is the set of URLs to which the home tab context + can be navigated to. All navigations within the application to a URL + within the home tab scope will be done in the home tab context, and + all other navigations will be done in a different application + context. +

    +

    + The home tab scope consists of the start_url and URLs that match a + pattern specified in the scope_patterns field. +

    + +
    +

    + scope_patterns member +

    +

    + The home tab scope_patterns member is a list of URLPatterns that + define the scope of the home tab. +

    +

    + If navigating from the home tab context to a URL url that is + outside of the home tab scope the following steps are run: +

    +
      +
    1. Create a new application context in the current window. +
    2. +
    3. Navigate it to url. +
    4. +
    +

    + If navigating to a URL url within the home tab scope, the following + steps are run: +

    +
      +
    1. Focus the home tab context. +
    2. +
    3. Navigate it to url. +
    4. +
    +
    +
    +
    +

    + new_tab_button member +

    +

    + The tab_strip new_tab_button member is an ordered map that describes + the behaviour of a UI affordance (such as a button) which, when + clicked/activated, opens a new application context within the + application window. It has the following members: +

    +
      +
    • [=new_tab_button/url=] +
    • +
    +

    + If url is within the home tab scope, then the new tab button may be + hidden. +

    +
    +

    + url member +

    +

    + The new_tab_button’s url member is a string that represents a URL + relative to the manifest URL that is within scope of a processed + manifest. This URL will be navigated to when the new tab button is + activated. +

    +
    +
    +
    +

    + Processing tab_strip member +

    To process the tab_strip member, given ordered map json, ordered + map manifest, URL manifest_URL, run the following during the extension + point in processing a manifest: +
      +
    1. Set manifest["tab_strip"] to a new ordered map. +
    2. +
    3. Set manifest["tab_strip"]["new_tab_button"]["url"] to start_url. +
    4. +
    5. If json["tab_strip"] does not exist, return. +
    6. +
    7. If the type of json["tab_strip"] is not ordered map, return. +
    8. +
    9. Process the home_tab member passing json["tab_strip"], + manifest["tab_strip"], and manifest_URL. +
    10. +
    11. Process the new_tab_button member passing json["tab_strip"], + manifest["tab_strip"], and manifest_URL. +
    12. +
    +
    +
    +

    + Processing home_tab member +

    To process the home_tab member, given ordered map json, ordered + map manifest_tab_strip, URL manifest_URL, run the following: +
      +
    1. If json["home_tab"] does not exist, or is not an ordered map, + return. +
    2. +
    3. Let home_tab be a new ordered map. +
    4. +
    5. Process the scope_patterns member passing + json["home_tab"]["scope_patterns"], home_tab. +
    6. +
    7. Set manifest_tab_strip["home_tab"] to home_tab. +
    8. +
    +
    +
    +

    + Processing the new_tab_button member +

    To process the new_tab_button member, given ordered map json, + ordered map manifest_tab_strip, URL manifest_URL, run the following: +
      +
    1. Set manifest_tab_strip["new_tab_button"]["url"] to start_url. +
    2. +
    3. If json["new_tab_button"] does not exist, or is not an ordered + map, return. +
    4. +
    5. Let url be the result of parsing json["new_tab_button"]["url"] + with manifest_URL as the base URL. +
    6. +
    7. If url is failure, return. +
    8. +
    9. If url is not within scope of manifest_URL, return. +
    10. +
    11. Set manifest_tab_strip["new_tab_button"]["url"] to url. +
    12. +
    +
    +
    +

    + Processing the scope_patterns member +

    To process the scope_patterns member, given ordered map json, + ordered map manifest_home_tab, run the following: +
      +
    1. Let processedScopePatterns be a new list. +
    2. +
    3. Set manifest_home_tab["scope_patterns"] to + processedScopePatterns. +
    4. +
    5. If json["scope_patterns"] doesn't exist or json["scope_patterns"] + is not a list, return. +
    6. +
    7. For each entry of json["scope_patterns"]: +
        +
      1. If entry is not an ordered map, continue. +
      2. +
      3. If entry["pathname"] does not exist, or is not a string, + continue. +
      4. +
      5. Let pattern be a URLPattern. +
      6. +
      7. Run the steps to initialize a URLPattern given pattern, + entry["pathname"], scope and default options. +
      8. +
      9. Append pattern to processedScopePatterns. +
      10. +
      +
    8. +
    +
    +

    From 2defed98c344556d87a41cbf4a829c50871fd46a Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 4 Mar 2024 17:25:36 +1100 Subject: [PATCH 05/42] Linkify concepts. --- index.html | 93 +++++++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/index.html b/index.html index e33a8af..65936ac 100644 --- a/index.html +++ b/index.html @@ -252,109 +252,110 @@

    - home_tab member + home_tab member

    - The home_tab member of the tab_strip object is an ordered map that - contains information about a specially marked application context - that, if it exists, is in every app window. This application context - has special properties compared to other application contexts, such - as restricted navigation and it SHOULD have a different appearance. + The `home_tab` member of the [=tab_strip=] object is an ordered map + that contains information about a specially marked [=application + context=] that, if it exists, is in every app window. This + application context has special properties compared to other + application contexts, such as restricted navigation and it SHOULD + have a different appearance.

    - A home tab context is the application context in which these special - properties are applied. + A home tab context is the [=application context=] in which + these special properties are applied.

    - If the home_tab member is not present, then the application is not - intended to have a home tab context, otherwise it is an ordered map - with the following members: + If the [=tab_strip/home_tab=] member is not present, then the + application is not intended to have a home tab context, otherwise it + is an ordered map with the following members:

    • [=home_tab/scope_patterns=]

    - How the home tab context is presented is at the discretion of the + How the [=home tab context=] is presented is at the discretion of the user agent.

    - The home tab scope is the set of URLs to which the home tab context - can be navigated to. All navigations within the application to a URL - within the home tab scope will be done in the home tab context, and - all other navigations will be done in a different application - context. + The home tab scope is the set of URLs to which the home + tab context can be navigated to. All navigations within the + application to a URL within the home tab scope will be done in the + [=home tab context=], and all other navigations will be done in a + different [=application context=].

    - The home tab scope consists of the start_url and URLs that match a - pattern specified in the scope_patterns field. + The [=home tab scope=] consists of the [=start URL=] and URLs that + match a pattern specified in the [=scope_patterns=] field.

    - scope_patterns member + scope_patterns member

    - The home tab scope_patterns member is a list of URLPatterns that - define the scope of the home tab. + The [=home_tab/scope_patterns=] member is a list of [=URLPattern=]s + that define the scope of the home tab.

    - If navigating from the home tab context to a URL url that is - outside of the home tab scope the following steps are run: + If navigating from the home tab context to a [=URL=] |URL:url| that + is outside of the [=home tab scope=], the following steps are run:

      -
    1. Create a new application context in the current window. +
    2. Create a new [=application context=] in the current window.
    3. -
    4. Navigate it to url. +
    5. Navigate it to |url|.

    - If navigating to a URL url within the home tab scope, the following - steps are run: + If navigating to a [=URL=] |URL:url| within the [=home tab scope=], + the following steps are run:

      -
    1. Focus the home tab context. +
    2. Focus the [=home tab context=].
    3. -
    4. Navigate it to url. +
    5. Navigate it to |url|.

    - new_tab_button member + new_tab_button member

    - The tab_strip new_tab_button member is an ordered map that describes - the behaviour of a UI affordance (such as a button) which, when - clicked/activated, opens a new application context within the - application window. It has the following members: + The [=tab_strip/new_tab_button=] member is an ordered map that + describes the behaviour of a UI affordance (such as a button) which, + when clicked/activated, opens a new [=application context=] within + the application window. It has the following members:

    • [=new_tab_button/url=]

    - If url is within the home tab scope, then the new tab button may be - hidden. + If [=new_tab_button/url=] is within the [=home tab scope=], then the + new tab button may be hidden.

    - url member + url member

    - The new_tab_button’s url member is a string that represents a URL - relative to the manifest URL that is within scope of a processed - manifest. This URL will be navigated to when the new tab button is - activated. + The [=url=] member is a string that represents a URL relative to + the [=manifest URL=] that is [=within scope=] of a [=processed + manifest=]. This URL will be navigated to when the new tab button + is activated.

    From 945db039e39eff586fb9b68ff5907a1254194886 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Wed, 6 Mar 2024 14:27:51 +1100 Subject: [PATCH 06/42] Format processing steps. --- index.html | 106 ++++++++++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 49 deletions(-) diff --git a/index.html b/index.html index 65936ac..4889f4a 100644 --- a/index.html +++ b/index.html @@ -361,94 +361,102 @@

    - Processing tab_strip member -

    To process the tab_strip member, given ordered map json, ordered - map manifest, URL manifest_URL, run the following during the extension - point in processing a manifest: + Processing the `tab_strip` member +

    To process the `tab_strip` member, given [=ordered + map=] |json:ordered map|, [=ordered map=] |manifest:ordered map|, and + [=URL=] |manifest URL:URL|, run the following during the extension + point in [=processing a manifest=]:
      -
    1. Set manifest["tab_strip"] to a new ordered map. -
    2. -
    3. Set manifest["tab_strip"]["new_tab_button"]["url"] to start_url. +
    4. Set |manifest|["tab_strip"] to a new [=ordered map=].
    5. -
    6. If json["tab_strip"] does not exist, return. +
    7. Set |manifest|["tab_strip"]["new_tab_button"]["url"] to + |manifest|["start_url"].
    8. -
    9. If the type of json["tab_strip"] is not ordered map, return. +
    10. If |json|["tab_strip"] does not exist or |json|["tab_strip"] is + not an [=ordered map=], return.
    11. -
    12. Process the home_tab member passing json["tab_strip"], - manifest["tab_strip"], and manifest_URL. +
    13. [=Process the `home_tab` member=] passing |json|["tab_strip"], + |manifest|["tab_strip"], and |manifest URL|.
    14. -
    15. Process the new_tab_button member passing json["tab_strip"], - manifest["tab_strip"], and manifest_URL. +
    16. [=Process the `new_tab_button` member=] passing + |json|["tab_strip"], |manifest|["tab_strip"], |manifest URL|, and + |manifest|["start_url"].

    - Processing home_tab member -

    To process the home_tab member, given ordered map json, ordered - map manifest_tab_strip, URL manifest_URL, run the following: + Processing the `home_tab` member +

    To process the `home_tab` member, given [=ordered map=] + |json:ordered map|, [=ordered map=] |manifest tab strip:ordered map|, + and [=URL=] |manifest URL:URL|, run the following:
      -
    1. If json["home_tab"] does not exist, or is not an ordered map, - return. +
    2. If |json|["home_tab"] does not exist or |json|["home_tab"] not an + [=ordered map=], return.
    3. -
    4. Let home_tab be a new ordered map. +
    5. Let |home tab:ordered map| be a new [=ordered map=].
    6. -
    7. Process the scope_patterns member passing - json["home_tab"]["scope_patterns"], home_tab. +
    8. [=Process the `scope_patterns` member=] passing + |json|["home_tab"]["scope_patterns"] and |home tab|.
    9. -
    10. Set manifest_tab_strip["home_tab"] to home_tab. +
    11. Set |manifest tab strip|["home_tab"] to |home tab|.

    - Processing the new_tab_button member -

    To process the new_tab_button member, given ordered map json, - ordered map manifest_tab_strip, URL manifest_URL, run the following: + Processing the `new_tab_button` member +

    To process the `new_tab_button` member, given [=ordered + map=] |json:ordered map|, [=ordered map=] |manifest tab strip:ordered + map|, [=URL=] |manifest URL:URL|, and [=URL=] |start URL:URL|, run the + following:
      -
    1. Set manifest_tab_strip["new_tab_button"]["url"] to start_url. +
    2. Set |manifest tab strip|["new_tab_button"]["url"] to |start URL|.
    3. -
    4. If json["new_tab_button"] does not exist, or is not an ordered - map, return. +
    5. If |json|["new_tab_button"] does not exist or + |json|["new_tab_button"] is not an [=ordered map=], return.
    6. -
    7. Let url be the result of parsing json["new_tab_button"]["url"] - with manifest_URL as the base URL. +
    8. Let |url:URL| be the result of [=URL Parser|parsing=] + |json|["new_tab_button"]["url"] with |manifest URL| as the base URL.
    9. -
    10. If url is failure, return. +
    11. If |url| is failure, return.
    12. -
    13. If url is not within scope of manifest_URL, return. +
    14. If |url| is not [=within scope=] of |manifest URL|, return.
    15. -
    16. Set manifest_tab_strip["new_tab_button"]["url"] to url. +
    17. Set |manifest tab strip|["new_tab_button"]["url"] to |url|.

    - Processing the scope_patterns member -

    To process the scope_patterns member, given ordered map json, - ordered map manifest_home_tab, run the following: + Processing the `scope_patterns` member + To process the `scope_patterns` member, given [=ordered + map=] |json:ordered map|, [=ordered map=] |manifest home tab:ordered + map|, run the following:
      -
    1. Let processedScopePatterns be a new list. +
    2. Let |processed scope patterns:list| be a new list.
    3. -
    4. Set manifest_home_tab["scope_patterns"] to - processedScopePatterns. +
    5. Set |manifest home tab|["scope_patterns"] to |processed scope + patterns|.
    6. -
    7. If json["scope_patterns"] doesn't exist or json["scope_patterns"] - is not a list, return. +
    8. If |json|["scope_patterns"] doesn't exist or + |json|["scope_patterns"] is not a list, return.
    9. -
    10. For each entry of json["scope_patterns"]: +
    11. For each |entry:ordered map| of |json|["scope_patterns"]:
        -
      1. If entry is not an ordered map, continue. +
      2. If |entry| is not an [=ordered map=], continue.
      3. -
      4. If entry["pathname"] does not exist, or is not a string, - continue. +
      5. If |entry|["pathname"] does not exist, or is not a + [=string=], continue.
      6. -
      7. Let pattern be a URLPattern. +
      8. Let |pattern:URLPattern| be a [=URLPattern=].
      9. -
      10. Run the steps to initialize a URLPattern given pattern, - entry["pathname"], scope and default options. +
      11. Run the steps to initialize a [=URLPattern=] given |pattern|, + |entry|["pathname"], scope + and default options.
      12. -
      13. Append pattern to processedScopePatterns. +
      14. Append |pattern| to |processed scope patterns|.
    12. From ea83f9f2b2917bb774eeaf32ac5cfa3129cc9be3 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Wed, 6 Mar 2024 17:03:24 +1100 Subject: [PATCH 07/42] Fix up links and add notes to be fixed up. --- index.html | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index 4889f4a..57282ec 100644 --- a/index.html +++ b/index.html @@ -24,6 +24,7 @@ "file-system-access", "fs", "mimesniff", + "urlpattern", "web-app-launch", "window-controls-overlay" ], @@ -304,8 +305,8 @@

      scope_patterns member

      - The [=home_tab/scope_patterns=] member is a list of [=URLPattern=]s - that define the scope of the home tab. + The [=home_tab/scope_patterns=] member is a list of [=URL + pattern=]s that define the scope of the home tab.

      If navigating from the home tab context to a [=URL=] |URL:url| that @@ -353,10 +354,14 @@

      The [=url=] member is a string that represents a URL relative to - the [=manifest URL=] that is [=within scope=] of a [=processed - manifest=]. This URL will be navigated to when the new tab button - is activated. + the [=manifest URL=] that is [=manifest/within scope=] of a + [=Document/processed manifest=]. This URL will be navigated to when + the new tab button is activated.

      +
    @@ -422,7 +427,7 @@

  • If |url| is failure, return.
  • -
  • If |url| is not [=within scope=] of |manifest URL|, return. +
  • If |url| is not [=URL/within scope=] of |manifest URL|, return.
  • Set |manifest tab strip|["new_tab_button"]["url"] to |url|.
  • @@ -450,17 +455,28 @@

  • If |entry|["pathname"] does not exist, or is not a [=string=], continue.
  • -
  • Let |pattern:URLPattern| be a [=URLPattern=]. -
  • -
  • Run the steps to initialize a [=URLPattern=] given |pattern|, - |entry|["pathname"], scope - and default options. +
  • Let |pattern:URL pattern| be the result of [=URL + pattern/create|creating=] a [=URL pattern=] given + |entry|["pathname"] and |scope:URL|.
  • Append |pattern| to |processed scope patterns|.
  • + +

    - If the [=home_tab=] member is validly specified, every application - window SHOULD feature an [=application context=] called the home - tab context that has special properties compared to other - application contexts. If [=home_tab=] is not present or not valid, - then the application windows SHOULD NOT have a [=home tab context=]. + The home tab context is an optional [=application + context=] that has special properties compared to other application + contexts. If the [=home_tab=] member is validly specified, every + application window SHOULD feature a [=home tab context=]. If + [=home_tab=] is not present or not valid, then the application + windows SHOULD NOT have a [=home tab context=].

    How the [=home tab context=] is presented is at the discretion of the user agent, but it SHOULD have a different appearance to normal tabs.

    - The home tab scope is a set of [=URLs=] which comprises - the union of the [=start URL=] and all URLs |url:URL| to which - applying [=URL pattern/match=] given any element of the - [=scope_patterns=] field and |url| returns a {{URLPatternResult}}. + The home tab scope is a set of [=URLs=] which, if + [=home_tab=] is validly specified, comprises the union of the [=start + URL=] and all URLs |url:URL| to which applying [=URL pattern/match=] + given any element of the [=scope_patterns=] field and |url| returns a + {{URLPatternResult}}. If [=home_tab=] is not present or not valid, + then the [=home tab scope=] is the empty set.

    A URL is said to be within home tab scope if it is a member of the [=home tab scope=]. It is outside of home tab scope if it is not a member of [=home tab scope=].

    -

    - Be more clear that [=home tab scope=] is not defined when `home_tab` - is not given (as opposed to the above, which implies that it defaults - to [=start URL=]). -

    +

    + An application has a home tab if the [=processed + manifest=] includes a non-null [=home_tab=] member of the + [=tab_strip=] member. +

    The home tab context is an optional [=application context=] that has special properties compared to other application - contexts. If the [=home_tab=] member is validly specified, every - application window SHOULD feature a [=home tab context=]. If - [=home_tab=] is not present or not valid, then the application - windows SHOULD NOT have a [=home tab context=]. + contexts. If the application [=has a home tab=], every application + window SHOULD feature a [=home tab context=]. If not, then the + application windows SHOULD NOT have a [=home tab context=].

    How the [=home tab context=] is presented is at the discretion of the user agent, but it SHOULD have a different appearance to normal tabs.

    - The home tab scope is a set of [=URLs=] which, if - [=home_tab=] is validly specified, comprises the union of the [=start + The home tab scope is a set of [=URLs=] which, if the + application [=has a home tab=], comprises the union of the [=start URL=] and all URLs |url:URL| to which applying [=URL pattern/match=] - given any element of the [=scope_patterns=] field and |url| returns a - {{URLPatternResult}}. If [=home_tab=] is not present or not valid, - then the [=home tab scope=] is the empty set. + given any element of the [=scope_patterns=] member of the + [=home_tab=] member of the [=tab_strip=] member of the [=processed + manifest=] and |url| returns a {{URLPatternResult}}. If the + application does not [=has a home tab|have a home tab=], then the + [=home tab scope=] is the empty set.

    A URL is said to be within home tab scope if it is a From 80ef095b450ccad7282063f7f1b789a21be73e9b Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 18 Mar 2024 15:30:52 +1100 Subject: [PATCH 20/42] Minor refactor. --- index.html | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index a675105..416e306 100644 --- a/index.html +++ b/index.html @@ -454,11 +454,15 @@

    1. Set |manifest|["tab_strip"] to a new [=ordered map=].
    2. -
    3. Set |manifest|["tab_strip"]["new_tab_button"]["url"] to - |manifest|["start_url"]. -
    4. If |json|["tab_strip"] does not exist or |json|["tab_strip"] is - not an [=ordered map=], return. + not an [=ordered map=]: +
        +
      1. Set |manifest|["tab_strip"]["new_tab_button"]["url"] to + |manifest|["start_url"]. +
      2. +
      3. Return. +
      4. +
    5. [=Process the `home_tab` member=] passing |json|["tab_strip"], |manifest|["tab_strip"], and |manifest URL|. From dffed052afa72950bb9af8af31179488e8cb82c9 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Wed, 20 Mar 2024 17:43:33 +1100 Subject: [PATCH 21/42] Move the check of the new tab button being outside of home tab scope into the parser. --- index.html | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/index.html b/index.html index 416e306..f7465cd 100644 --- a/index.html +++ b/index.html @@ -414,6 +414,10 @@

      [=manifest URL=] that is [=manifest/within scope=] of a [=Document/processed manifest=].

      +

      When the new tab button is activated by the end user, the following steps are run: @@ -426,19 +430,6 @@

      [=new_tab_button=].

    -

    - If [=new_tab_button/url=] is [=within home tab scope=], then the user - agent MUST hide the new tab button. -

    - -

    - This should probably be stronger: check if it matches in the parser - and ignore it. Add a note here. -

    @@ -520,9 +511,16 @@

  • If |url| is not [=URL/within scope=] of |manifest URL|, return.
  • +
  • If |url| is [=within home tab scope=], return. +
  • Set |manifest tab strip|["new_tab_button"]["url"] to |url|.
  • +

    From bb737f61989af362d70b430dfe3125f099e31367 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Thu, 21 Mar 2024 14:03:59 +1100 Subject: [PATCH 22/42] Added a note about History API. --- index.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/index.html b/index.html index f7465cd..06556ed 100644 --- a/index.html +++ b/index.html @@ -337,6 +337,14 @@

    context/initial URL=] is [=outside of home tab scope=]. +

    The rule about "[=initial URL=] is [=within home tab scope=]" is based on the understanding that "initial URL" refers to the current From 268d2cfcfc04310af53b909636eae9a7598b290a Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Thu, 21 Mar 2024 14:04:07 +1100 Subject: [PATCH 23/42] Use 'has a home tab'. --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 06556ed..887c731 100644 --- a/index.html +++ b/index.html @@ -323,7 +323,7 @@

    the [=home tab scope=].

    - When a [=home tab scope=] is defined, the user agent SHOULD ensure + When an application [=has a home tab=], the user agent SHOULD ensure that at all times:

      From 3df45bcb48f6ad97c64cd8ebe631ff3bfe4f074e Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Thu, 21 Mar 2024 14:44:28 +1100 Subject: [PATCH 24/42] Added usage example. --- index.html | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 887c731..c0d23b8 100644 --- a/index.html +++ b/index.html @@ -567,11 +567,39 @@

    -
    +

    Usage Example

    -

    +
    +        {
    +          "name": "Tabbed App Example",
    +          "start_url": "/",
    +          "display": "standalone",
    +          "display_override": ["tabbed"],
    +          "tab_strip": {
    +            "home_tab": {
    +              "scope_patterns": [
    +                "/",
    +                "/index.html"
    +              ]
    +            },
    +            "new_tab_button": {
    +              "url": "/create"
    +            }
    +          }
    +        }
    +        
    +

    + This example is a tabbed web app that falls back to a single-document + standalone window if tabbed mode is not supported. Any navigation to + the main index page (either / or + /index.html) is opened in the [=home tab context=]. Note + that query parameters are ignored by default (so a navigation to + /index.html?utm_source=foo will match the home tab + scope). The new tab button will open a new tab at + /create. +

    From 40b89bca219fb4dd99cd87f0b7cfe4a5d034e341 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Thu, 21 Mar 2024 16:30:33 +1100 Subject: [PATCH 25/42] Fix link to processed manifest. --- index.html | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index c0d23b8..a1e52a6 100644 --- a/index.html +++ b/index.html @@ -255,7 +255,6 @@

    "manifest URL" and "start URL" need to be exported from APPMANIFEST. See w3c/manifest#1112. - Also, "processed manifest".

    @@ -283,7 +282,7 @@

    [[urlpattern]] for more information.

    - An application has a home tab if the [=processed + An application has a home tab if the [=Document/processed manifest=] includes a non-null [=home_tab=] member of the [=tab_strip=] member.

    @@ -303,10 +302,10 @@

    application [=has a home tab=], comprises the union of the [=start URL=] and all URLs |url:URL| to which applying [=URL pattern/match=] given any element of the [=scope_patterns=] member of the - [=home_tab=] member of the [=tab_strip=] member of the [=processed - manifest=] and |url| returns a {{URLPatternResult}}. If the - application does not [=has a home tab|have a home tab=], then the - [=home tab scope=] is the empty set. + [=home_tab=] member of the [=tab_strip=] member of the + [=Document/processed manifest=] and |url| returns a + {{URLPatternResult}}. If the application does not [=has a home + tab|have a home tab=], then the [=home tab scope=] is the empty set.

    A URL is said to be within home tab scope if it is a From 176b7541900a3277cf707bb76e6b6777248a95dc Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 25 Mar 2024 15:22:07 +1100 Subject: [PATCH 26/42] Use build a URL pattern instead of hand-creating a dictionary. --- index.html | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/index.html b/index.html index a1e52a6..eac4ac8 100644 --- a/index.html +++ b/index.html @@ -549,15 +549,10 @@

  • For each |entry:URLPatternInit| of |json|["scope_patterns"]:
      -
    1. If |entry| is not a {{URLPatternInput}}, continue. -
    2. -
    3. If |entry| is a {{URLPatternInit}}, set |entry|["baseURL"] - to |manifest URL|, and let |base URL| be null. Otherwise, let - |base URL| be |manifest URL|. -
    4. -
    5. Let |pattern:URL pattern| be the result of [=URL - pattern/create|creating=] a [=URL pattern=] given |entry| and - |base URL|. If this process throws, continue. +
    6. Let |pattern:URL pattern| be the result of [=build a URL + pattern from an infra value|building a URL pattern from an + infra value=] |entry| given |manifest URL|. If this process + throws or returns null, continue.
    7. Append |pattern| to |processed scope patterns|.
    8. From d902a2329cc019c804b75b2f5b93365b3c33b5a7 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 25 Mar 2024 17:27:57 +1100 Subject: [PATCH 27/42] Invoke process the tab_strip member. --- index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.html b/index.html index eac4ac8..146deef 100644 --- a/index.html +++ b/index.html @@ -223,6 +223,9 @@

      |json:ordered map|, and [=ordered map=] |manifest:ordered map|):

        +
      1. [=Process the `tab_strip` member=], passing |json|, |manifest| and + |manifest URL|. +
      2. [=Process the `note_taking` member=], passing |json|, |manifest| and |manifest URL|.
      3. From 2bf8cae82a0cda2898bac99902454db3e9b15f4a Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 25 Mar 2024 17:30:00 +1100 Subject: [PATCH 28/42] Properly define new_tab_button/url. --- index.html | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index 146deef..da3e953 100644 --- a/index.html +++ b/index.html @@ -415,14 +415,11 @@

      4. [=new_tab_button/url=]
      5. -

        - "url" is already defined as a member of another struct. This is - causing linking issues. -

        - The [=url=] member is a string that represents a URL relative to the - [=manifest URL=] that is [=manifest/within scope=] of a - [=Document/processed manifest=]. + The url member + is a string that represents a URL relative to the [=manifest URL=] + that is [=manifest/within scope=] of a [=Document/processed + manifest=].

    +

  • From 365d460c0bfacced50b63c4ffbf7f0c698cec37b Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 22 Apr 2024 12:14:35 +1000 Subject: [PATCH 31/42] Refactor definition of home tab scope. Define a boolean condition first, rather than defining a set. Makes it more readable. Also exclude fragments (but not query). --- index.html | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/index.html b/index.html index dbc33a8..c313b74 100644 --- a/index.html +++ b/index.html @@ -296,28 +296,39 @@

    user agent, but it SHOULD have a different appearance to normal tabs.

    - The home tab scope is a set of [=URLs=] which, if the - application [=has a home tab=], comprises the union of the [=start - URL=] and all URLs |url:URL| to which applying [=URL pattern/match=] - given any element of the [=scope_patterns=] member of the - [=home_tab=] member of the [=tab_strip=] member of the - [=Document/processed manifest=] and |url| returns a - {{URLPatternResult}}. If the application does not [=has a home - tab|have a home tab=], then the [=home tab scope=] is the empty set. + A [=URL=] |url:URL| is said to be within home tab scope if + and only if the application [=has a home tab=] and at least one of + the following conditions are met:

    +
      +
    • |url| [=URL/equals=] the [=start URL=], with [=URL/equals/exclude + fragments=] set to true. +
    • +
    • Applying [=URL pattern/match=] given any element of the + [=scope_patterns=] member of the [=home_tab=] member of the + [=tab_strip=] member of the [=Document/processed manifest=] and |url| + returns a {{URLPatternResult}}. +
    • +

    - A URL is said to be within home tab scope if it is a - member of the [=home tab scope=]. It is outside of home tab - scope if it is not a member of [=home tab scope=]. + The home tab scope is the set of [=URLs=] which are + [=within home tab scope=]. A URL is is outside of home tab + scope if it is not [=within home tab scope=].

    When an application [=has a home tab=], the user agent SHOULD ensure From 374724d11cc218d6a8fd69d77d7df0597f46cbd1 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 22 Apr 2024 12:22:38 +1000 Subject: [PATCH 32/42] exclude URLs outside of manifest scope from being in home scope. --- index.html | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index c313b74..7458fbf 100644 --- a/index.html +++ b/index.html @@ -297,17 +297,24 @@

    A [=URL=] |url:URL| is said to be within home tab scope if - and only if the application [=has a home tab=] and at least one of - the following conditions are met: + and only if:

      -
    • |url| [=URL/equals=] the [=start URL=], with [=URL/equals/exclude - fragments=] set to true. +
    • the application [=has a home tab=], and
    • -
    • Applying [=URL pattern/match=] given any element of the - [=scope_patterns=] member of the [=home_tab=] member of the - [=tab_strip=] member of the [=Document/processed manifest=] and |url| - returns a {{URLPatternResult}}. +
    • |url| is [=manifest/within scope=] of the manifest, and +
    • +
    • at least one of the following: +
        +
      • |url| [=URL/equals=] the [=start URL=], with + [=URL/equals/exclude fragments=] set to true, or +
      • +
      • Applying [=URL pattern/match=] given any element of the + [=scope_patterns=] member of the [=home_tab=] member of the + [=tab_strip=] member of the [=Document/processed manifest=] and + |url| returns a {{URLPatternResult}}. +
      • +

    From fd980526f4834adbe3ec85621a1f11128c8878e9 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 22 Apr 2024 15:19:12 +1000 Subject: [PATCH 33/42] Remove the official definition of home tab scope, as it is only used non-normatively, and just talk about it as an idea, not a formal term. Add a note about ignoring the fragment but not the query. --- index.html | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index 7458fbf..8d28f51 100644 --- a/index.html +++ b/index.html @@ -270,8 +270,8 @@

    The scope_patterns member is a list of - {{URLPatternInput}}s that define the [=home tab scope|scope of the - home tab=] relative to the [=manifest URL=]. + {{URLPatternInput}}s that define the [=within home tab scope|scope of + the home tab=] relative to the [=manifest URL=].

    From 3a3ba0519149be4fa9a8682b634267b6293368e9 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Mon, 22 Apr 2024 17:27:38 +1000 Subject: [PATCH 35/42] Rewrote invariants concerning home tab scope. Now, the three invariants are non-normative discussion of what is intended, rather than a hard rule. The normative logic elsewhere should speak for itself. This way, we do not need to formally find a concept of 'initial URL' and can just informally talk about documents that rewrite their URL. --- index.html | 92 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/index.html b/index.html index 478e33a..d653f91 100644 --- a/index.html +++ b/index.html @@ -342,47 +342,19 @@

    then the home tab scope is the empty set.

    -

    - When an application [=has a home tab=], the user agent SHOULD ensure - that at all times: -

    -
      -
    • every application window has exactly one [=home tab context=], - and -
    • -
    • every [=home tab context=]'s [=browsing context/initial URL=] is - [=within home tab scope=], and -
    • -
    • every non-home-tab [=application context=]'s [=browsing - context/initial URL=] is [=outside of home tab scope=]. -
    • -
    - -

    - The rule about "[=initial URL=] is [=within home tab scope=]" is - based on the understanding that "initial URL" refers to the current - URL of the document (not simply the URL initially loaded into the - application context). The "initial" simply refers to not taking into - account changes made to the display URL via the History API. Verify - this and possibly add a note. Also, this is not linkable. Find a way - to reference this aspect of the context (possibly via document). -

    -

    - In order to ensure the above rule that "every application window has - exactly one [=home tab context=]", the user agent will need to create - a new [=home tab context=] whenever a new application window is - created, for example when launching the application, or when moving a - tab to a new window. A newly created [=home tab context=] SHOULD be - navigated to the [=start URL=], which by definition is [=within home - tab scope=]. -

    +
    +

    + Every window has a home tab +

    +

    + If the application [=has a home tab=], whenever a new application + window is created (for example when launching the application, or + when moving a tab to a new window), the user agent MUST create a + new [=home tab context=] in that window. A newly created [=home tab + context=] SHOULD be navigated to the [=start URL=], which by + definition is [=within home tab scope=]. +

    +

    Navigations concerning the home tab scope @@ -418,6 +390,44 @@

    left behind does not end up in an unexpected state.

    +
    +

    + Home tab invariants +

    +

    + The above rules are intended to ensure that the following + invariants are always true, for applications that [=has a home + tab|have a home tab=]: +

    +
      +
    • every application window has exactly one [=home tab context=], + and +
    • +
    • every [=home tab context=]'s active document's [=Document/URL=] + is [=within home tab scope=] (unless the document's URL has changed + since it was created), and +
    • +
    • every non-home-tab [=application context=]'s active document's + [=Document/URL=] is [=outside of home tab scope=] (unless the + document's URL has changed since it was created). +
    • +
    +

    + User agents will not dynamically move documents between home-tab + and non-home-tab contexts if they change their [=URL/fragment=], or + use the {{History}} API to modify their display URL into or out of + the home tab scope, because no navigation is taking place. For this + reason, the above invariants only care about the [=Document/URLs=] + that documents had at the time of their creation. +

    +

    + Applications that "pretend" to navigate by modifing their URLs can + detect when they are in tabbed application mode and change their + behaviour to perform actual navigations into and out of the home + tab scope, rather than modifying the URL, to ensure the user agent + correctly opens documents in or out of the [=home tab context=]. +

    +

    From 957cb9e70295e5814e9b1acb052780d52a09c864 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Wed, 24 Apr 2024 11:13:02 +1000 Subject: [PATCH 36/42] Fix the logic of whether the app has a new tab button. Now has an explicit concept of "has a new tab button" (analogous to "has a home tab"). The parser algorithm no longer (accidentally) sets the new tab URL to the start URL if it is within home tab scope. Add a note clarifying why the new tab button is not allowed to be in home tab scope. Also note the start URL default, which is easy to miss as it is buried in the parser algorithm. --- index.html | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index d653f91..3548377 100644 --- a/index.html +++ b/index.html @@ -339,7 +339,8 @@

    If the application does not [=has a home tab|have a home tab=], - then the home tab scope is the empty set. + then the home tab scope is the empty set, and all URLs are + [=outside of home tab scope=].

    @@ -449,9 +450,28 @@

    that is [=manifest/within scope=] of a [=Document/processed manifest=].

    +

    + An application has a new tab button if the + [=Document/processed manifest=]'s [=new_tab_button=]'s + [=new_tab_button/url=] member is [=outside of home tab scope=]. If + the application does not [=has a new tab button|have a new tab + button=], the user agent SHOULD NOT make the "new tab" affordance + available to the end user. +

    When the new tab button is activated by the end user, the following @@ -546,16 +566,9 @@

  • If |url| is not [=URL/within scope=] of |manifest URL|, return.
  • -
  • If |url| is [=within home tab scope=], return. -
  • Set |manifest tab strip|["new_tab_button"]["url"] to |url|.
  • -

    From afd09db424c7548f3c7aa5dbaa23c417335ec2ce Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Wed, 24 Apr 2024 16:28:28 +1000 Subject: [PATCH 37/42] Respond to loubrett review. --- index.html | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 3548377..2fb7c6b 100644 --- a/index.html +++ b/index.html @@ -280,9 +280,10 @@

    [[urlpattern]] for more information.

    - An application has a home tab if the [=Document/processed - manifest=] includes a non-null [=home_tab=] member of the - [=tab_strip=] member. + An application has a home tab if the applied [=display + mode=] of the application is [=display mode/tabbed=], and the + [=Document/processed manifest=] includes a non-null [=home_tab=] + member of the [=tab_strip=] member.

    The home tab context is an optional [=application @@ -293,7 +294,8 @@

    How the [=home tab context=] is presented is at the discretion of the - user agent, but it SHOULD have a different appearance to normal tabs. + user agent, but it SHOULD have a different appearance to normal + application contexts.

    A [=URL=] |url:URL| is said to be within home tab scope if @@ -330,7 +332,8 @@

    tab context=], and all navigations to a URL [=outside of home tab scope=] will be performed in a different [=application context=] (i.e., another tab), creating one if necessary. The application's - [=start URL=] is always part of the home tab scope. + [=start URL=] is always part of the home tab scope (if the + application [=has a home tab=]).

    For the purpose of matching against the [=start URL=], the From e41c10c88e41ecd5febd3f02bc54956fec330baf Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Wed, 24 Apr 2024 16:39:03 +1000 Subject: [PATCH 38/42] Some basic response to dmurph review. --- index.html | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index 2fb7c6b..e7b0964 100644 --- a/index.html +++ b/index.html @@ -364,19 +364,20 @@

    Navigations concerning the home tab scope

    - If navigating from the [=home tab context=] to a [=URL=] |url:URL| - that is [=outside of home tab scope=], the following steps are run: + If [=navigate|navigating=] from the [=home tab context=] to a + [=URL=] |url:URL| that is [=outside of home tab scope=], the + following steps are run:

      -
    1. Create a new [=application context=] in the current window and +
    2. [=Create a new application context=] in the current window and focus it.
    3. Navigate it to |url|.

    - If navigating to a [=URL=] |url:URL| [=within home tab scope=], the - following steps are run: + If [=navigate|navigating=] to a [=URL=] |url:URL| [=within home tab + scope=], the following steps are run:

    1. Focus the [=home tab context=]. @@ -481,7 +482,7 @@

      steps are run:

        -
      1. Create a new [=application context=] in the current window and +
      2. [=Create a new application context=] in the current window and focus it.
      3. Navigate it to the value of the [=new_tab_button/url=] member of From 809805468474624f3fe97f1700cb083b51519d21 Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Fri, 26 Apr 2024 13:57:18 +1000 Subject: [PATCH 39/42] Rewrote confusing advice for developers. --- index.html | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index e7b0964..e16ebc4 100644 --- a/index.html +++ b/index.html @@ -426,11 +426,15 @@

        that documents had at the time of their creation.

        - Applications that "pretend" to navigate by modifing their URLs can - detect when they are in tabbed application mode and change their - behaviour to perform actual navigations into and out of the home - tab scope, rather than modifying the URL, to ensure the user agent - correctly opens documents in or out of the [=home tab context=]. + For single-page applications that "pretend" to navigate by + modifying their URLs, this may result in undesirable behaviour that + breaks the above invariants (e.g. if the user clicks a link from + the home tab to dynamically change the URL to a non-home page, they + will stay inside the home tab because it is not actually + navigating). To avoid this situation, the application can detect + when it is in tabbed application mode and change its behavior to + perform actual navigations into and out of the home tab scope, + rather than modifying the URL.

    From c9037cb0a08382c9a4119d0122df7edd611d629d Mon Sep 17 00:00:00 2001 From: Matt Giuca Date: Fri, 26 Apr 2024 15:40:55 +1000 Subject: [PATCH 40/42] Rewrite navigations concerning the home tab scope. Done in consultation with dmurph and loubrett, to make the navigation rules much clearer and hook into the HTML navigable machinery. --- index.html | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index e16ebc4..f9817b7 100644 --- a/index.html +++ b/index.html @@ -364,25 +364,51 @@

    Navigations concerning the home tab scope

    - If [=navigate|navigating=] from the [=home tab context=] to a - [=URL=] |url:URL| that is [=outside of home tab scope=], the - following steps are run: + When [=navigate|navigating=] the [=top-level traversable=] + associated with a [=home tab context=] to a [=URL=] |url:URL| that + is [=outside of home tab scope=], the following steps are run:

      -
    1. [=Create a new application context=] in the current window and - focus it. +
    2. Let [=top-level traversable=] |tab:toplevel traversable| be the + result of choosing a navigable with a target of + "_blank" and noopener true.
    3. -
    4. Navigate it to |url|. +
    5. Instead of [=navigating=] the home-tab traversable, + [=navigate=] |tab| with the same parameters. +
    6. +
    7. [=applied|Apply=] the current [=application manifest=] to + |tab|'s [=top-level browsing context=]. +
    8. +
    9. The user agent SHOULD place |tab| in the same window as the + home-tab navigable. +
    10. +
    11. Focus |tab|.
    +

    + The [[HTML]] spec defines + rules for choosing a navigable, mentioned above. However, it is + not exported, so it is unable to be properly linked, and may be + considered a layering violation. +

    - If [=navigate|navigating=] to a [=URL=] |url:URL| [=within home tab - scope=], the following steps are run: + When [=navigate|navigating=] a [=top-level traversable=] with a + [=display mode=] of [=display mode/tabbed=] that is not associated + with a [=home tab context=] (i.e. a non-home tab) to a [=URL=] + |url:URL| that is [=within home tab scope=], the following steps + are run:

      -
    1. Focus the [=home tab context=]. +
    2. Let |hometab:toplevel traversable| be the [=top-level + traversable=] of the [=home tab context=] associated with the + current window. +
    3. +
    4. Instead of [=navigating=] the top-level traversable, + [=navigate=] |hometab| with the same parameters.
    5. -
    6. Navigate it to |url|. +
    7. Focus |hometab|.