Rewrite Step 9 of getNetworkService algorithm following feedback @ http://lists.w3.org/Archives/Public/public-device-apis/2012Sep/0141.html
authorRich Tibbett <richt@opera.com>
Mon, 04 Feb 2013 13:47:41 +0100
changeset 3718b03e17da083
parent 370 ffdaef94ac31
child 372 7639401e21f4
Rewrite Step 9 of getNetworkService algorithm following feedback @ http://lists.w3.org/Archives/Public/public-device-apis/2012Sep/0141.html
discovery-api/Overview.src.html
     1.1 --- a/discovery-api/Overview.src.html	Fri Feb 01 10:43:20 2013 +0200
     1.2 +++ b/discovery-api/Overview.src.html	Mon Feb 04 13:47:41 2013 +0100
     1.3 @@ -124,8 +124,8 @@
     1.4        <p>
     1.5          Using this <abbr title="Application Programming Interface">API</abbr> consists of requesting a well-known
     1.6          service type, known by developers and advertised by Local-networked Devices. User authorization, where the user
     1.7 -        connects the web page to discovered services, is expected before the web page is able to interact
     1.8 -        with any Local-networked Services.
     1.9 +        connects the web page to discovered services, is expected before the web page is able to interact with any
    1.10 +        Local-networked Services.
    1.11        </p>
    1.12        <p>
    1.13          A web page creates a request to obtain connectivity to services running in the network by specifying a
    1.14 @@ -271,17 +271,15 @@
    1.15        </p>
    1.16        <p>
    1.17          A <dfn>valid service type</dfn> is any of the following:
    1.18 -        <ul>
    1.19 -           <li>
    1.20 -              a string that begins with <code>upnp:</code> or <code>zeroconf:</code>
    1.21 -              followed by one or more characters in the ranges U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to U+002E,
    1.22 -              U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E.
    1.23 -           </li>
    1.24 -           <li>
    1.25 -              a string that begins with <code>dial:</code> followed by an integer version.
    1.26 -           </li>
    1.27 -        </ul>
    1.28        </p>
    1.29 +      <ul>
    1.30 +        <li>a string that begins with <code>upnp:</code> or <code>zeroconf:</code> followed by one or more characters
    1.31 +        in the ranges U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to U+002E, U+0030 to U+0039, U+0041 to U+005A,
    1.32 +        U+005E to U+007E.
    1.33 +        </li>
    1.34 +        <li>a string that begins with <code>dial:</code> followed by an integer version.
    1.35 +        </li>
    1.36 +      </ul>
    1.37        <p>
    1.38          A <a>valid service type</a> provided in the <code>type</code> attribute of the <a href=
    1.39          "#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a> method will be matched against the
    1.40 @@ -344,8 +342,8 @@
    1.41            </dt>
    1.42            <dd>
    1.43              <p>
    1.44 -              Prompts the user to select discovered network services that have advertised support for the
    1.45 -              requested service type.
    1.46 +              Prompts the user to select discovered network services that have advertised support for the requested
    1.47 +              service type.
    1.48              </p>
    1.49              <p>
    1.50                The <var title="">type</var> argument contains one or more <a>valid service type</a> tokens that the web
    1.51 @@ -427,21 +425,31 @@
    1.52                    "#dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></a>) as its
    1.53                    argument, abort any remaining steps and return.
    1.54              </li>
    1.55 -            <li>If <var>services found</var> is not an empty array then the <a>user agent</a> MUST prompt the user in a
    1.56 -              user-agent-specific manner for permission to provide
    1.57 -            the <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
    1.58 -                  class="externalDFN">entry script</a>'s <a href=
    1.59 -                  "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
    1.60 -                  class="externalDFN">origin</a> with an array of <a href=
    1.61 -                  "#networkservice"><code>NetworkService</code></a> objects representing the <a>user-authorized</a> subset
    1.62 -                  of <var>services found</var>.
    1.63 +            <li>The user agent MUST NOT provide the entry script's origin with a <a href=
    1.64 +            "#networkservices"><code>NetworkServices</code></a> object without prior permission given by the user.
    1.65                <p>
    1.66 -                If the user grants permission to access one or more networked services then the <a>user agent</a>
    1.67 -                SHOULD include an "ongoing local-network communication" indicator.
    1.68 +                If <var>services found</var> is not an empty array then the <a>user agent</a> MAY choose to prompt the
    1.69 +                user in a user-agent-specific manner for permission to provide the <a href=
    1.70 +                "http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
    1.71 +                   class="externalDFN">entry script</a>'s <a href=
    1.72 +                   "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
    1.73 +                   class="externalDFN">origin</a> with a <a href="#networkservices"><code>NetworkServices</code></a>
    1.74 +                   object representing the <a>user-authorized</a> subset of <var>services found</var>.
    1.75                </p>
    1.76                <p>
    1.77 -                If the user denies permission, then the <a>user agent</a> MUST <a href=
    1.78 -                "http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task"
    1.79 +                Alternatively, the user agent MAY choose to queue a task to invoke <var>successCallback</var> or
    1.80 +                <var>errorCallback</var> immediately based on a previously-established user preference, for security
    1.81 +                reasons, or due to platform limitations. In such an implementation, if <var>successCallback</var> is to
    1.82 +                be fired as a result of a previously-established user preference then the <a>user agent</a> MUST
    1.83 +                continue at the next step of this algorithm.
    1.84 +              </p>
    1.85 +              <p>
    1.86 +                If permission has been granted by the user to access one or more networked services then the <a>user
    1.87 +                agent</a> SHOULD include an "ongoing local-network communication" indicator.
    1.88 +              </p>
    1.89 +              <p>
    1.90 +                If permission has been denied by the user, <a>user agent</a> or platform, then the <a>user agent</a>
    1.91 +                MUST <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task"
    1.92                     class="externalDFN">queue a task</a> to invoke <var>errorCallback</var>, if it is provided and is an
    1.93                     object of type <code>Function</code>, with a new <a href=
    1.94                     "#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object whose <a href=
    1.95 @@ -451,15 +459,15 @@
    1.96                     argument, abort any remaining steps and return.
    1.97                </p>
    1.98                <p>
    1.99 -                If the user never responds, this algorithm stalls on this step.
   1.100 +                If the user never responds or no previously-established user preference has been met, this algorithm
   1.101 +                stalls on this step.
   1.102                </p>
   1.103              </li>
   1.104              <li>Let <var>services</var> be an empty array.
   1.105              </li>
   1.106 -            <li>
   1.107 -               If <var>services found</var> is not an empty array then set <var>services</var> to be an array of one or more <a href=
   1.108 -            "#networkservice"><code>NetworkService</code></a> objects for which the user granted permission above - known as the
   1.109 -            current objects <dfn>user-authorized</dfn> services.
   1.110 +            <li>If <var>services found</var> is not an empty array then set <var>services</var> to be an array of one
   1.111 +            or more <a href="#networkservice"><code>NetworkService</code></a> objects for which the user granted
   1.112 +            permission above - known as the current objects <dfn>user-authorized</dfn> services.
   1.113              </li>
   1.114              <li>For each Object <var>service</var> in <var>services</var>, if any, run the following sub-steps:
   1.115                <ol class="rule">
   1.116 @@ -480,9 +488,9 @@
   1.117              items currently found in the <a>list of available service records</a> whose <code>type</code> property
   1.118              matches any of the tokens requested in <var>requested control types</var>.
   1.119              </li>
   1.120 -            <li>Add <var>services</var>, if any, to the <var>services manager</var> object as its collection of <a>indexed
   1.121 -            properties</a>. If <var>services</var> is an empty array then the <var>services manager</var> does not have any
   1.122 -            <var>indexed properties</var>.
   1.123 +            <li>Add <var>services</var>, if any, to the <var>services manager</var> object as its collection of
   1.124 +            <a>indexed properties</a>. If <var>services</var> is an empty array then the <var>services manager</var>
   1.125 +            does not have any <var>indexed properties</var>.
   1.126              </li>
   1.127              <li>Set <var>services manager</var>'s <a href="#dom-networkservices-length"><code>length</code></a>
   1.128              attribute to the number of items in <var>services</var>.
   1.129 @@ -515,15 +523,14 @@
   1.130                 Web Messaging, XMLHttpRequest).
   1.131            </p>
   1.132            <p>
   1.133 -            If the user navigates away from the
   1.134 -            <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
   1.135 -                  class="externalDFN">entry script</a>'s <a href=
   1.136 -                  "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
   1.137 -                  class="externalDFN">origin</a> then the <a>user agent</a> <em class=
   1.138 -            "ct">MUST</em> remove all previously whitelisted urls from the <a>entry script origin's URL whitelist</a>.
   1.139 -            There is no persistence to network service selections provided to a web page. It is not possible to access
   1.140 -            a previously white-listed networked service without the necessary user authorization in all of the
   1.141 -            following cases:
   1.142 +            If the user navigates away from the <a href=
   1.143 +            "http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
   1.144 +               class="externalDFN">entry script</a>'s <a href=
   1.145 +               "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
   1.146 +               class="externalDFN">origin</a> then the <a>user agent</a> <em class="ct">MUST</em> remove all previously
   1.147 +               whitelisted urls from the <a>entry script origin's URL whitelist</a>. There is no persistence to network
   1.148 +               service selections provided to a web page. It is not possible to access a previously white-listed
   1.149 +               networked service without the necessary user authorization in all of the following cases:
   1.150            </p>
   1.151            <ul>
   1.152              <li>If the current script is reloaded at any point in the same or different window.
   1.153 @@ -589,14 +596,13 @@
   1.154          Obtaining networked services
   1.155        </h2>
   1.156        <p>
   1.157 -        The <a href="#networkservices"><code>NetworkServices</code></a> interface represents a collection of zero
   1.158 -        or more <dfn>indexed properties</dfn> that are
   1.159 -        each a <a>user-authorized</a> <a href="#networkservice"><code>NetworkService</code></a> object.
   1.160 +        The <a href="#networkservices"><code>NetworkServices</code></a> interface represents a collection of zero or
   1.161 +        more <dfn>indexed properties</dfn> that are each a <a>user-authorized</a> <a href=
   1.162 +        "#networkservice"><code>NetworkService</code></a> object.
   1.163        </p>
   1.164        <p>
   1.165          A <a href="#networkservices"><code>NetworkServices</code></a> object is the top level success callback
   1.166 -        parameter from a call to
   1.167 -        <a href="#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a>.
   1.168 +        parameter from a call to <a href="#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a>.
   1.169        </p>
   1.170        <pre class="widl">
   1.171  [NoInterfaceObject]
   1.172 @@ -686,11 +692,11 @@
   1.173            </dd>
   1.174          </dl>
   1.175          <p>
   1.176 -          A <a href="#networkservices"><code>NetworkServices</code></a> object represents the current collection of zero
   1.177 -          or more <a href="#networkservice"><code>NetworkService</code></a> objects - its <a>indexed properties</a>. A <a href=
   1.178 -          "#networkservices"><code>NetworkServices</code></a> object is <span>immutable</span> meaning that
   1.179 -          <a>indexed properties</a> cannot be added and <a>indexed properties</a> cannot be removed for the lifetime of
   1.180 -          a <a href="#networkservices"><code>NetworkServices</code></a> object.
   1.181 +          A <a href="#networkservices"><code>NetworkServices</code></a> object represents the current collection of
   1.182 +          zero or more <a href="#networkservice"><code>NetworkService</code></a> objects - its <a>indexed
   1.183 +          properties</a>. A <a href="#networkservices"><code>NetworkServices</code></a> object is
   1.184 +          <span>immutable</span> meaning that <a>indexed properties</a> cannot be added and <a>indexed properties</a>
   1.185 +          cannot be removed for the lifetime of a <a href="#networkservices"><code>NetworkServices</code></a> object.
   1.186          </p>
   1.187          <p class="note">
   1.188            Each service in a <a href="#networkservices"><code>NetworkServices</code></a> object thus has an index; the
   1.189 @@ -966,12 +972,12 @@
   1.190        <p>
   1.191          A <a>user agent</a> conforming to this specification MAY implement <abbr title=
   1.192          "Simple Service Discovery Protocol">SSDP</abbr> [[!UPNP-DEVICEARCH11]], Zeroconf [[!DNS-SD]] + [[!MDNS]] or
   1.193 -        <abbr title="Discovery and Launch Protocol">DIAL</abbr> [<a href = "https://sites.google.com/a/dial-multiscreen.org/dial/dial-protocol-specification">DIAL</a>]
   1.194 -        <dfn>service discovery mechanisms</dfn> - the requirements detailed in this section of the specification - to
   1.195 -        enable Web pages to request and connect with HTTP services running on networked devices, discovered via either
   1.196 -        mechanism, through this API. When a <a>user agent</a> implements either of these <a>service discovery
   1.197 -        mechanisms</a>, then it MUST conform to the corresponding algorithms provided in this section of the
   1.198 -        specification.
   1.199 +        <abbr title="Discovery and Launch Protocol">DIAL</abbr> [<a href=
   1.200 +        "https://sites.google.com/a/dial-multiscreen.org/dial/dial-protocol-specification">DIAL</a>] <dfn>service
   1.201 +        discovery mechanisms</dfn> - the requirements detailed in this section of the specification - to enable Web
   1.202 +        pages to request and connect with HTTP services running on networked devices, discovered via either mechanism,
   1.203 +        through this API. When a <a>user agent</a> implements either of these <a>service discovery mechanisms</a>, then
   1.204 +        it MUST conform to the corresponding algorithms provided in this section of the specification.
   1.205        </p>
   1.206        <p>
   1.207          This section presents how the results of these two <a>service discovery mechanisms</a> will be matched to
   1.208 @@ -994,9 +1000,8 @@
   1.209        <p>
   1.210          The <dfn>list of active service managers</dfn> is an internal list within user agents that is used to track all
   1.211          <a href="#networkservices"><code>NetworkServices</code></a> objects currently being shared with any web pages
   1.212 -        at the current time within the user agent. Each <a href="#networkservices"><code>NetworkServices</code></a> object
   1.213 -        in the <a>list of
   1.214 -        active service managers</a> represents a collection of zero or more <a href=
   1.215 +        at the current time within the user agent. Each <a href="#networkservices"><code>NetworkServices</code></a>
   1.216 +        object in the <a>list of active service managers</a> represents a collection of zero or more <a href=
   1.217          "#networkservice"><code>NetworkService</code></a> objects - known as its <dfn>indexed properties</dfn>.
   1.218          <a href="#networkservice"><code>NetworkService</code></a> objects are attached as the <a>indexed properties</a>
   1.219          of a <a href="#networkservices"><code>NetworkServices</code></a> object as part of the <a href=
   1.220 @@ -1470,43 +1475,42 @@
   1.221          <h5>
   1.222            Discovery and Launch Protocol (<abbr title="Discovery and Launch Protocol">DIAL</abbr>)
   1.223          </h5>
   1.224 -         <p>
   1.225 +        <p>
   1.226            A user agent that implements DIAL service discovery MUST issue a <dfn>search request for DIAL-enabled
   1.227            devices</dfn> against the user's current local network according to the full normative text and timing
   1.228            provided in 'Section 1.3.2: Search request with M-SEARCH' detailed in [[!UPNP-DEVICEARCH11]].
   1.229          </p>
   1.230          <p>
   1.231 -          Let <var>dial version</var> be the version number specified in the <a>valid service type</a> token.
   1.232 -          Let <var>dial search target</var> be the concatentation of the
   1.233 +          Let <var>dial version</var> be the version number specified in the <a>valid service type</a> token. Let
   1.234 +          <var>dial search target</var> be the concatentation of the
   1.235            <code>urn:dial-multiscreen-org:service:dial:</code> string constant with the <var>dial version</var>
   1.236            (currently, <var>dial version</var> can only be <code>1</code>)
   1.237          </p>
   1.238          <p>
   1.239 -          The user agent MUST issue all <a title="search request for DIAL devices">search requests for DIAL
   1.240 -          devices</a> with a HTTP request line equal to <code>M-SEARCH * HTTP/1.1</code>, with a HOST header equal to
   1.241 -          the reserved multicast address and port of <code>239.255.255.250:1900</code>, a MAN header equal to
   1.242 -          <code>ssdp:discover</code>, an ST header equal to <var>dial search target</var>
   1.243 -          and a user-agent defined MX header equal to a <dfn>maximum DIAL advertisement response wait time</dfn>
   1.244 -          value between <code>1</code> and <code>5</code> seconds.
   1.245 +          The user agent MUST issue all <a title="search request for DIAL devices">search requests for DIAL devices</a>
   1.246 +          with a HTTP request line equal to <code>M-SEARCH * HTTP/1.1</code>, with a HOST header equal to the reserved
   1.247 +          multicast address and port of <code>239.255.255.250:1900</code>, a MAN header equal to
   1.248 +          <code>ssdp:discover</code>, an ST header equal to <var>dial search target</var> and a user-agent defined MX
   1.249 +          header equal to a <dfn>maximum DIAL advertisement response wait time</dfn> value between <code>1</code> and
   1.250 +          <code>5</code> seconds.
   1.251          </p>
   1.252          <p>
   1.253            The user agent MUST listen for any incoming responses to a <a>search request for DIAL devices</a>.
   1.254          </p>
   1.255          <p>
   1.256 -          For each HTTP Response following an initial <a>search request for DIAL devices</a> sent on a
   1.257 -          <a>standard UPnP address and port</a> the user agent MUST run the following steps:
   1.258 +          For each HTTP Response following an initial <a>search request for DIAL devices</a> sent on a <a>standard UPnP
   1.259 +          address and port</a> the user agent MUST run the following steps:
   1.260          </p>
   1.261          <ol class="rule">
   1.262 -          <li>If the HTTP Response is not a HTTP 200 OK response then this response is invalid and the user
   1.263 -          agent MUST discard this response, abort any remaining steps and return. The user agent MAY issue a new
   1.264 -          <a>search request for DIAL devices</a> as a result of this error occurring.
   1.265 +          <li>If the HTTP Response is not a HTTP 200 OK response then this response is invalid and the user agent MUST
   1.266 +          discard this response, abort any remaining steps and return. The user agent MAY issue a new <a>search request
   1.267 +          for DIAL devices</a> as a result of this error occurring.
   1.268            </li>
   1.269            <li>If the <a>maximum DIAL advertisement response wait time</a> has been exceeded since the initial <a>search
   1.270            request for DIAL devices</a> was sent then the <a>HTTP Response</a> is invalid and the user agent MUST
   1.271            discard this response, abort any remaining steps and return. The user agent MAY stop listening for responses
   1.272 -          from the current <a>search request for DIAL devices</a> as a result of this error occurring. Equally,
   1.273 -          the user agent MAY issue a new <a>search request for DIAL devices</a> as a result of this error
   1.274 -          occurring.
   1.275 +          from the current <a>search request for DIAL devices</a> as a result of this error occurring. Equally, the
   1.276 +          user agent MAY issue a new <a>search request for DIAL devices</a> as a result of this error occurring.
   1.277            </li>
   1.278            <li>Let <var>dial device</var> be an Object with a property for each HTTP header received in the <a>HTTP
   1.279            Response</a>, with each key being the name of a HTTP response header and each value being that HTTP response
   1.280 @@ -1514,9 +1518,8 @@
   1.281            </li>
   1.282            <li>If <var>dial device</var> does not contain at least one <var>CACHE-CONTROL</var> entry, at least one
   1.283            <var>USN</var> entry, at least one <var>ST</var> entry and at least one <var>LOCATION</var> entry or the
   1.284 -          value of its <var>ST</var> entry is not <var>dial search target</var>, then the
   1.285 -          <a>HTTP Response</a> is invalid and the <a>user agent</a> MUST discard this response, abort any remaining
   1.286 -          steps and return.
   1.287 +          value of its <var>ST</var> entry is not <var>dial search target</var>, then the <a>HTTP Response</a> is
   1.288 +          invalid and the <a>user agent</a> MUST discard this response, abort any remaining steps and return.
   1.289            </li>
   1.290            <li>The user agent MUST run the rule for <a>obtaining a UPnP Device Description File</a> passing in the first
   1.291            occurrence of <var>LOCATION</var> from <var>dial device</var> as the <var>device descriptor URL</var>
   1.292 @@ -1537,12 +1540,12 @@
   1.293            description using HTTP' in [[!UPNP-DEVICEARCH11]].
   1.294            </li>
   1.295            <li>Let <var>application url</var> be the value of the first occurrence of the <code>Application-URL</code>
   1.296 -          response header field obtained according to the rules defined in 'Section 5.4: Device Description Response' in
   1.297 -          [<a href = "https://sites.google.com/a/dial-multiscreen.org/dial/dial-protocol-specification">DIAL</a>]
   1.298 +          response header field obtained according to the rules defined in 'Section 5.4: Device Description Response'
   1.299 +          in [<a href="https://sites.google.com/a/dial-multiscreen.org/dial/dial-protocol-specification">DIAL</a>]
   1.300            </li>
   1.301            <li>If the value provided in <var>device descriptor URL</var> cannot be resolved as a reachable URL on the
   1.302 -          current network or the <var>device descriptor file</var> remains empty or <var>application url</var> is undefined
   1.303 -          then it is invalid and the <a>user agent</a> MUST abort any remaining steps and return.
   1.304 +          current network or the <var>device descriptor file</var> remains empty or <var>application url</var> is
   1.305 +          undefined then it is invalid and the <a>user agent</a> MUST abort any remaining steps and return.
   1.306            </li>
   1.307            <li>Run the following steps to add the newly discovered DIAL service:
   1.308              <ol class="rule">
   1.309 @@ -1562,8 +1565,8 @@
   1.310                </li>
   1.311                <li>Set <var>network service record</var>'s <code>type</code> property to <var>dial search target</var>.
   1.312                </li>
   1.313 -              <li>Set <var>network service record</var>'s <code>url</code> property to the string value of the <var>
   1.314 -              application url</var>.
   1.315 +              <li>Set <var>network service record</var>'s <code>url</code> property to the string value of the
   1.316 +              <var>application url</var>.
   1.317                </li>
   1.318                <li>Set <var>network service record</var>'s <code>expiryTimestamp</code> property to the value of the
   1.319                current date, in UTC timestamp format, plus the value of <var>device expiry</var>.
   1.320 @@ -1689,12 +1692,11 @@
   1.321        </h3>
   1.322        <p>
   1.323          A user agent MUST only garbage collect a <a><code>NetworkServices</code></a> object and remove its entry from
   1.324 -        the <a>list of active service managers</a> when the user has navigated away from the
   1.325 -        <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
   1.326 -              class="externalDFN">entry script</a>'s <a href=
   1.327 -              "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
   1.328 -              class="externalDFN">origin</a> in which
   1.329 -        the current <a><code>NetworkServices</code></a> object was provided.
   1.330 +        the <a>list of active service managers</a> when the user has navigated away from the <a href=
   1.331 +        "http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
   1.332 +           class="externalDFN">entry script</a>'s <a href=
   1.333 +           "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
   1.334 +           class="externalDFN">origin</a> in which the current <a><code>NetworkServices</code></a> object was provided.
   1.335        </p>
   1.336        <p>
   1.337          A user agent MUST NOT garbage collect individual <a><code>NetworkService</code></a> objects until their parent