discovery-api/Overview.src.html
author Rich Tibbett <richt@opera.com>
Wed, 22 Aug 2012 16:50:21 +0200
changeset 195 76074ec7e535
parent 194 ad608906c611
child 197 383c29793d6b
permissions -rw-r--r--
Clean up the UPnP Update Service Monitor
     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <title>Networked Service Discovery and Messaging</title>
     5     <meta http-equiv='Content-Type' content='text/html;charset=utf-8'/>
     6     <script type="text/javascript" class='remove'>
     7       var respecConfig = {
     8           specStatus:   "ED",
     9           //publishDate:  "2012-08-22",
    10           shortName:    "discovery-api",
    11           edDraftURI:   "http://w3c-test.org/dap/discovery-api/",
    12           previousMaturity: "WD",
    13           previousPublishDate: "2012-08-07",
    14           editors: [
    15             {
    16               name:       "Rich Tibbett",
    17               //url:        "http://richt.me/",
    18               company:    "Opera Software ASA",
    19               companyURL: "http://opera.com/"
    20             },
    21             {
    22               name:       "Clarke Stevens",
    23               //url:      "",
    24               company:    "CableLabs",
    25               companyURL: "http://cablelabs.com/"
    26             }
    27           ],
    28           noIDLIn:      true,
    29           wg:           "Device APIs and Policy Working Group",
    30           wgURI:        "http://www.w3.org/2009/dap/",
    31           wgPublicList: "public-device-apis",
    32           wgPatentURI:  "http://www.w3.org/2004/01/pp-impl/43696/status"
    33       };
    34     </script>
    35 
    36     <script src='http://www.w3.org/Tools/respec/respec-w3c-common' type="text/javascript" class='remove' async></script>
    37     <style type="text/css">
    38       /* Custom CSS optimizations (Richard Tibbett) */
    39 
    40       /* Add better spacing to sections */
    41       section, .section { margin-bottom: 2em; }
    42 
    43       /* Reduce note & issue render size */
    44       .note, .issue { font-size:0.8em; }
    45 
    46       /* Add addition spacing to <ol> and <ul> for rule definition */
    47       ol.rule li, ul.rule li { padding:0.6em; }
    48 
    49       pre.widl { border: solid thin; background: #EEEEEE; color: black; padding: 0.5em 1em; position: relative; }
    50       pre.widl :link, pre.widl :visited { color: #000; background: transparent; }
    51       pre.widl:before { content: "IDL"; font: bold small sans-serif; padding: 0.5em; background: white; position: absolute; top: 0; margin: -1px 0 0 -4em; width: 1.5em; border: thin solid; border-radius: 0 0 0 0.5em }
    52 
    53       div.example { border: solid thin red; background: #F7DFE5; color: black; padding: 0.5em 1em; position: relative; margin: 1em 0 1em 4.6em; width: auto; }
    54       div.example:before { content: "EXAMPLE"; font: bold small sans-serif; padding: 0.5em; background: red; color: white; position: absolute; top: 0; margin: -1px 0 0 -7.6em; width: 5em; border: thin solid red; border-radius: 0 0 0 0.5em }
    55 
    56       dl.domintro { color: green; margin: 2em 0 2em 2em; padding: 0.5em 1em; border: none; background: #DDFFDD; }
    57       hr + dl.domintro, div.impl + dl.domintro { margin-top: 2.5em; margin-bottom: 1.5em; }
    58       dl.domintro dt, dl.domintro dt * { color: black; text-decoration: none; }
    59       dl.domintro dd { margin: 0.5em 0 1em 2em; padding: 0; }
    60       dl.domintro dd p { margin: 0.5em 0; }
    61       dl.domintro code {font-size: inherit; font-style: italic; }
    62       dl.domintro:before { display: table; margin: -1em -0.5em 0.5em auto; width: auto; content: 'This box is non-normative. Implementation requirements are given below this box.'; color: red; border: solid 2px; background: white; padding: 0 0.25em; }
    63     </style>
    64   </head>
    65 
    66   <body>
    67     <section id='abstract'>
    68       <p>
    69         This specification defines a mechanism for an HTML document to discover and subsequently communicate with <abbr title="Hypertext Transfer Protocol">HTTP</abbr>-based services
    70         advertised via common discovery protocols within a user's network.
    71       </p>
    72     </section>
    73 
    74     <section id='sotd'>
    75       <p>
    76         This document represents the early consensus of the group on the scope and features of the proposed
    77         API.
    78       </p>
    79     </section>
    80 
    81     <section class="informative">
    82       <h3>Introduction</h3>
    83 
    84       <p>To enable Web pages to connect and communicate with Local-networked Services provided over HTTP, this specification introduces the
    85       <a href="#navigatornetworkservice"><code>NavigatorNetworkService</code></a> interface.</p>
    86 
    87       <p>
    88          Using this <abbr title="Application Programming Interface">API</abbr> consists of requesting a well-known service type, known by developers and advertised by Local-networked Devices. User authorization, where the user connects the web page to one or more discovered services,
    89          is expected before the web page is able to interact with any Local-networked Services.
    90       </p>
    91 
    92       <p>
    93          A web page creates a request to obtain connectivity to services running in the network by specifying a well-known discovery service type that it wishes to interact with.
    94       </p>
    95 
    96       <p>
    97          The user agent, having captured all advertised services on the network from the Service Discovery mechanisms included in this recommendation, attempts to match
    98       the requested service type to a discovered service according to the processing described herein.
    99       </p>
   100 
   101       <p>
   102           If a service connectivity request is successful then the Web page is provided with the necessary information to communicate with the authorized Local-networked Service.
   103           If the request fails then the Web page will receive an error callback containing an error code describing the cause of Local-networked Service connectivity failure.
   104       </p>
   105 
   106       <p>
   107          Once connected to a Local-networked Service the Web page can send requests and receive responses to the Local-networked Service via the messaging format and appropriate channel inferred from the service type
   108          authorized via the provided API.
   109          The Web page, once connected, can also receive service-pushed events, in the messaging format supported by the Local-networked Device, if such event subscription functionality is provided by the
   110          connected Local-networked Service.
   111       </p>
   112 
   113       <div class="example">
   114        <p>Example of requesting a DNS-SD advertised service:</p>
   115        <hr />
   116        <pre class="highlight">function showServices( services ) {
   117   // Show a list of all the services provided to the web page
   118   for(var i = 0, l = services.length; i < l; i++) console.log( services[i].name );
   119 }
   120 
   121 navigator.getNetworkServices('zeroconf:_boxee-jsonrpc._tcp', showServices);</pre>
   122       </div>
   123 
   124       <div class="example">
   125         <p>Example of requesting a UPnP advertised service, also handling error conditions:</p>
   126         <hr />
   127         <pre class="highlight">function showServices( services ) {
   128   // Show a list of all the services provided to the web page
   129   for(var i = 0, l = services.length; i < l; i++) console.log( services[i].name );
   130 }
   131 
   132 function error( e ) {
   133   console.log( "Error occurred: " + e.code );
   134 }
   135 
   136 navigator.getNetworkServices('upnp:urn:schemas-upnp-org:service:ContentDirectory:1', showServices, error);</pre>
   137       </div>
   138 
   139       <div class="example">
   140         <p>Example of requesting either a DNS-SD or UPnP advertised service:</p>
   141         <hr />
   142         <pre class="highlight">function showServices( services ) {
   143   // Show a list of all the services provided to the web page (+ service type)
   144   for(var i = 0, l = services.length; i < l; i++)
   145      console.log( services[i].name + '(' + services[i].type + ')' );
   146 }
   147 
   148 navigator.getNetworkServices([
   149   'zeroconf:_boxee-jsonrpc._tcp',
   150   'upnp:urn:schemas-upnp-org:service:ContentDirectory:1'
   151 ], showServices);</pre>
   152       </div>
   153 
   154       <p>For more detailed examples see the <a href="#examples">Examples</a> section.
   155     </section>
   156 
   157     <section
   158      id='conformance'>
   159 
   160      <p>Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the
   161      meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.</p>
   162 
   163      <p>
   164       Some conformance requirements are phrased as requirements on attributes, methods or objects. Such requirements are to be interpreted as requirements on user agents.
   165      </p>
   166 
   167      <p>
   168       Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in
   169       this specification are intended to be easy to follow, and not intended to be performant.)
   170      </p>
   171 
   172      <p>
   173       The only conformance class defined by this specification is a <dfn>user agent</dfn>.
   174      </p>
   175 
   176      <p>
   177       User agents may impose implementation-specific limits on otherwise unconstrained inputs, e.g. to prevent denial of service attacks, to guard against running out of memory, or to work
   178       around platform-specific limitations.
   179      </p>
   180 
   181      <p>
   182       When support for a feature is disabled (e.g. as an emergency measure to mitigate a security problem, or to aid in development, or for performance reasons), user agents must act as if
   183       they had no support for the feature whatsoever, and as if the feature was not mentioned in this specification. For example, if a particular feature is accessed via an attribute in a Web
   184       IDL interface, the attribute itself would be omitted from the objects that implement that interface - leaving the attribute on the object but making it return null or throw an exception
   185       is insufficient.
   186      </p>
   187 
   188       <section>
   189          <h3>Dependencies</h3>
   190 
   191          This specification relies on several other underlying specifications.
   192 
   193          <dl>
   194             <dt>HTML</dt>
   195             <dd>Many fundamental concepts from HTML are used by this specification. [[!HTML5]]</dd>
   196             <dt>WebIDL</dt>
   197             <dd>The IDL blocks in this specification use the semantics of the WebIDL specification. [[!WEBIDL]]</dd>
   198          </dl>
   199       </section>
   200     </section>
   201 
   202     <section>
   203       <h3>Terminology</h3>
   204 
   205       <p>
   206          The construction "a <code>Foo</code> object", where <code>Foo</code> is actually an interface, is sometimes used instead of the more accurate "an object implementing the interface <code>Foo</code>".
   207       </p>
   208 
   209       <p>
   210          The term DOM is used to refer to the API set made available to scripts in Web applications, and does not necessarily imply the existence of an actual <code>Document</code> object or of any
   211          other <code>Node</code> objects as defined in the DOM Core specifications. [[!DOM4]]
   212       </p>
   213 
   214       <p>
   215          An IDL attribute is said to be <em>getting</em> when its value is being retrieved (e.g. by author script), and is said to be <em>setting</em> when a new value is assigned to it.
   216       </p>
   217 
   218       <p>
   219         A <dfn>valid service type</dfn> is a string that begins with <code>upnp:</code> or <code>zeroconf:</code> 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, U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E.
   220       </p>
   221 
   222       <p>
   223         A <a>valid service type</a> provided in the <code>type</code> attribute of the <code>getNetworkServices()</code> method will be matched against the services currently contained in the <a>list of available service records</a> according to the algorithms defined in this specification.
   224       </p>
   225     </section>
   226 
   227     <section>
   228      <h2>Requesting networked services</h2>
   229 
   230 
   231 <pre class="widl">[Supplemental, NoInterfaceObject]
   232 interface <dfn id="navigatornetworkservice">NavigatorNetworkService</dfn> {
   233   // Obtain a Local-networked Service
   234   void <a href="#dom-navigator-getnetworkservices">getNetworkServices</a>( in any type,
   235                            in <a href="#navigatornetworkservicesuccesscallback">NavigatorNetworkServiceSuccessCallback</a> successCallback,
   236                            in optional <a href="#navigatornetworkserviceerrorcallback">NavigatorNetworkServiceErrorCallback</a> errorCallback );
   237 };
   238 <a class="externalDFN" href="http://www.whatwg.org/specs/web-apps/current-work/complete/timers.html#navigator">Navigator</a> implements <a href="#navigatornetworkservice">NavigatorNetworkService</a>;
   239 
   240 [Callback=FunctionOnly, NoInterfaceObject]
   241 interface <dfn id="navigatornetworkservicesuccesscallback">NavigatorNetworkServiceSuccessCallback</dfn> {
   242   void handleEvent( in <a href="#networkservices">NetworkServices</a> services );
   243 };
   244 
   245 [NoInterfaceObject]
   246 interface <dfn id="navigatornetworkserviceerror">NavigatorNetworkServiceError</dfn> {
   247   const unsigned short <a href="#dom-navigatornetworkserviceerror-permission_denied">PERMISSION_DENIED_ERR</a> = 1;
   248   const unsigned short <a href="#dom-navigatornetworkserviceerror-unknown_type_prefix">UNKNOWN_TYPE_PREFIX_ERR</a> = 2;
   249   readonly attribute unsigned short <a href="#dom-navigatornetworkserviceerror-code">code</a>;
   250 };
   251 
   252 [Callback=FunctionOnly, NoInterfaceObject]
   253 interface <dfn id="navigatornetworkserviceerrorcallback">NavigatorNetworkServiceErrorCallback</dfn> {
   254   void handleEvent( in <a href="#navigatornetworkserviceerror">NavigatorNetworkServiceError</a> error );
   255 };
   256 </pre>
   257 
   258   <section>
   259    <h2>Methods</h2>
   260 
   261       <dl class="domintro">
   262         <dt>
   263           <var title="">window</var>
   264            .
   265           <code title="dom-navigator">
   266             <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/timers.html#navigator">navigator</a>
   267           </code>
   268            .
   269           <code title="dom-navigator-getNetworkServices">
   270             <a href="#dom-navigator-getnetworkservices">getNetworkServices</a>
   271           </code>
   272           (
   273           <var title="">type</var>
   274           ,
   275           <var title="">successCallback</var>
   276            [,
   277           <var title="">errorCallback</var>
   278            ] )
   279         </dt>
   280         <dd>
   281           <p>Prompts the user to select one or more discovered network services that have advertised support for the requested service type.</p>
   282           <p>
   283             The
   284             <var title="">type</var>
   285              argument contains one or more <a>valid service type</a> tokens that the web page would like to interact with.
   286           </p>
   287           <p>
   288             If the user accepts, the
   289             <var title="">successCallback</var>
   290              is
   291           invoked, with one or more
   292             <code>
   293               <a href="#networkservice"><code>NetworkService</code></a>
   294             </code>
   295              objects as
   296           its argument.
   297           </p>
   298           <p>
   299             If the user declines, the
   300             <var title="">errorCallback</var>
   301              (if
   302           any) is invoked.
   303           </p>
   304         </dd>
   305       </dl>
   306 
   307        <div>
   308           <p>
   309             When the <dfn id="dom-navigator-getnetworkservices" title="dom-navigator-getnetworkservices"><code>getNetworkServices(type, successCallback[, errorCallback])</code></dfn> method is called, the <a>user agent</a> MUST run the following steps:
   310           </p>
   311 
   312           <ol class="rule">
   313 
   314             <li>
   315               Let <var>requested control types</var> be initially set to an empty array.
   316             </li>
   317 
   318             <li>
   319                If <var>type</var> is an array consisting of one or more <a>valid service type</a> tokens, then let <var>requested control types</var> by the value of <var>type</var>, removing any non-<a>valid service type</a> tokens from the resulting array.
   320             </li>
   321 
   322             <li>
   323                If <var>type</var> is a string consisting of one <a>valid service type</a> token, then let <var>requested control types</var> be an array containing one item with a value of <var>type</var>.
   324             </li>
   325 
   326             <li>
   327                If <var>requested control types</var> is an array that contains at least one or more <a title="valid service type">valid service type</a> tokens then continue to the step labeled <em>process</em> below. Otherwise, the <a>user agent</a> MUST <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a> to invoke <var>errorCallback</var>, if it is provided and is an object of type <code>Function</code>, with a new <a href="#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object whose
   328                  <a href="#dom-navigatornetworkserviceerror-code"><code>code</code></a> attribute has the numeric value 2
   329                   (<a href="#dom-navigatornetworkserviceerror-unknown_type_prefix"><code>UNKNOWN_TYPE_PREFIX_ERR</code></a>) as its argument,
   330                    abort any remaining steps and return.
   331             </li>
   332 
   333             <li>
   334                <em>Process</em>: Let <var>services found</var> be an empty array.
   335             </li>
   336 
   337             <li>
   338                For each <var>available service</var> in the <a>list of available service records</a> run the following steps:
   339                <ol class="rule">
   340                   <li>
   341                     For each <var>requested control type</var> in <var>requested control types</var>: If <var>available service</var>'s <code>type</code> attribute equals the <var>requested control type</var> then let <var>matched service</var> equal the value of <var>available service</var> and continue at the step labeled <var>attach</var> below.
   342                   </li>
   343                   <li>
   344                      Continue at the next <var>available service</var>.
   345                   </li>
   346                   <li>
   347                      <em>Attach</em>: If <var>matched service</var> is not empty then run the following steps:
   348 
   349                      <ol class="rule">
   350                         <li>
   351                            Let <var>new service object</var> be a new <a href="#networkservice"><code>NetworkService</code></a> object, mapping the parameters of
   352                      <var>matched service</var> to this new object where possible.
   353                         </li>
   354                         <li>
   355                            Append <var>new service object</var> to the <var>services found</var> array.
   356                         </li>
   357                      </ol>
   358                   </li>
   359                </ol>
   360             </li>
   361 
   362             <li>
   363                If <var>services found</var> is an empty array, then the <a>user agent</a> MUST <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a> to invoke <var>errorCallback</var>, if it is provided and is an object of type <code>Function</code>, with a new <a href="#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object whose
   364                  <a href="#dom-navigatornetworkserviceerror-code"><code>code</code></a> attribute has the numeric value 1
   365                  (<a href="#dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></a>) as its argument, abort any remaining steps and return.
   366             </li>
   367 
   368             <li>
   369                Return, and run the remaining steps asynchronously.
   370             </li>
   371 
   372             <li>
   373                Optionally, e.g. based on a previously-established user preference, for security reasons, or due to platform limitations, the <a>user agent</a> MAY <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a> to invoke <var>errorCallback</var>, if it is provided and is an object of type <code>Function</code>, with a new <a href="#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object whose
   374                  <a href="#dom-navigatornetworkserviceerror-code"><code>code</code></a> attribute has the numeric value 1
   375                  (<a href="#dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></a>) as its argument, abort any remaining steps and return.
   376             </li>
   377 
   378             <li>
   379                   The <a>user agent</a> MUST prompt the user in a user-agent-specific manner for permission to provide the
   380                   <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script" class="externalDFN">entry script</a>'s
   381                   <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin" class="externalDFN">origin</a> with an array of
   382                   <a href="#networkservice"><code>NetworkService</code></a> objects representing the user-authorized subset of <var>services found</var>.
   383 
   384                <p>
   385                   If the user grants permission to access one or more networked services then the <a>user agent</a> SHOULD include an
   386                   "ongoing local-network communication" indicator.
   387                </p>
   388 
   389                <p>If the user denies permission, then the <a>user agent</a> MUST <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a> to invoke <var>errorCallback</var>, if it is provided and is an object of type <code>Function</code>, with a new <a href="#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object whose
   390                 <a href="#dom-navigatornetworkserviceerror-code"><code>code</code></a> attribute has the numeric value 1
   391                 (<a href="#dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></a>) as its argument, abort any remaining steps and return.
   392               </p>
   393 
   394               <p>
   395                 If the user never responds, this algorithm stalls on this step.
   396               </p>
   397 
   398             </li>
   399 
   400             <li>
   401                Let <var>services</var> be the array of one or more <a href="#networkservice"><code>NetworkService</code></a> objects for which the user granted permission.
   402             </li>
   403 
   404             <li>
   405                For each Object <var>service</var> in <var>services</var>, run the following substeps:
   406 
   407                <ol class="rule">
   408                   <li>
   409                      Add the <var>service</var>'s <code>url</code> parameter to the <a>entry script origin's <abbr title="Uniform Resource Locator">URL</abbr> whitelist</a>.
   410                   </li>
   411                   <li>
   412                     If <var>service</var>'s <code>type</code> parameter begins with the DOMString &quot;<code>upnp:</code>&quot; and the <var>service</var>'s <code>eventsUrl</code> parameter is not empty then <a>setup a UPnP Events Subscription</a> for <var>service</var>.
   413                   </li>
   414                </ol>
   415             </li>
   416 
   417             <li>
   418                Let <var>services manager</var> be a new <a href="#networkservices"><code>NetworkServices</code></a> object.
   419             </li>
   420 
   421             <li>
   422                Set <var>services manager</var>'s <a href="#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute to the length of <var>services</var>.
   423             </li>
   424 
   425             <li>
   426               Store the set of <var>services</var> as <dfn id="current_authorized_services">current authorized services</dfn> internally against the newly created <var>services manager</var> object.
   427             </li>
   428 
   429             <li>
   430                The <a>user agent</a> MUST <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a> to invoke <var>successCallback</var> with
   431                <var>services manager</var> as its argument.
   432             </li>
   433 
   434           </ol>
   435 
   436           <p>
   437             The <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#task-source" class="externalDFN">task source</a> for these
   438             <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#concept-task" class="externalDFN">tasks</a> is the
   439             <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#user-interaction-task-source" class="externalDFN">user interaction task source</a>.
   440           </p>
   441 
   442           <p>
   443             When a <a href="#networkservice"><code>NetworkService</code></a> object is provided to a Web page, the <a>user agent</a> MUST add the <code>url</code> property
   444              to the <dfn>entry script origin's URL whitelist</dfn>. This list enables the
   445             Web page to override and initiate cross-site resource requests towards these URLs, and any sub-resources of these URLs, within the current
   446             <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script" class="externalDFN">entry script</a>'s
   447             <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin" class="externalDFN">origin</a> via various existing mechanisms (e.g. Web Sockets, Server-Sent Events,
   448             Web Messaging, XMLHttpRequest).
   449          </p>
   450 
   451          <p>
   452             If the user navigates away from the current browsing context, the <a>user agent</a> MUST remove all previously whitelisted urls from the <a>entry script origin's URL whitelist</a>.
   453             There is no persistence to network service selections provided to a web page. It is not possible to access a previously white-listed networked service without the necessary user authorization in all of the following cases:
   454             <ul>
   455               <li>If the current script is reloaded at any point in the same or different window.</li>
   456               <li>if the current script reinvokes the <a href="#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a> method at any point in its execution.</li>
   457               <li>If the user navigates forward or back in their history to reload the current page.</li>
   458               <li>If a script is running in a different origin.</li>
   459             </ul>
   460          </p>
   461 
   462       </div>
   463       </section>
   464 
   465       <section>
   466          <h3>Error Handling</h3>
   467 
   468       <dl class="domintro">
   469         <dt>
   470           <var title="">error</var>
   471            .
   472           <code title="dom-NavigatorNetworkServiceError-code">
   473             <a href="#dom-navigatornetworkserviceerror-code">code</a>
   474           </code>
   475         </dt>
   476         <dd>
   477           <p>
   478             Returns the current error's error code. At the current time, this may be <code>1</code> or <code>2</code>, for which the
   479             corresponding error constants
   480             <a href="#dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></a> and
   481             <a href="#dom-navigatornetworkserviceerror-unknown_type_prefix"><code>UNKNOWN_TYPE_PREFIX_ERR</code></a> are defined.
   482           </p>
   483         </dd>
   484       </dl>
   485 
   486          <p>
   487             The <dfn id="dom-navigatornetworkserviceerror-code" title="dom-navigatornetworkserviceerror-code"><code>code</code></dfn> attribute of a
   488             <a href="#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object MUST return the code for the error, which will be one of the following:
   489          </p>
   490 
   491          <dl>
   492             <dt>
   493                <dfn id="dom-navigatornetworkserviceerror-permission_denied" title="dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></dfn> (numeric value 1)
   494             </dt>
   495             <dd>
   496                The user or user agent denied the page permission to access any services.
   497             </dd>
   498             <dt>
   499                <dfn id="dom-navigatornetworkserviceerror-unknown_type_prefix" title="dom-navigatornetworkserviceerror-unknown_type_prefix"><code>UNKNOWN_TYPE_PREFIX_ERR</code></dfn> (numeric value 2)
   500             </dt>
   501             <dd>
   502                No <a>valid service type</a> tokens were provided in the method invocation.
   503             </dd>
   504          </dl>
   505 
   506       </section>
   507 
   508       </section>
   509       <section>
   510       <h2>Obtaining networked services</h2>
   511 
   512       <p>
   513          The <a href="#networkservices"><code>NetworkServices</code></a> interface is the top-level response object from a call to <a href="#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a> and provides access to a set of user-authorized <a href="#networkservice"><code>NetworkService</code></a> objects for the given request.
   514       </p>
   515 
   516 <pre class="widl">
   517 [NoInterfaceObject]
   518 interface <dfn id="networkservices">NetworkServices</dfn> {
   519   readonly attribute unsigned long    <a href="#dom-networkservices-length">length</a>;
   520   getter <a href="#networkservice">NetworkService</a> (unsigned long index);
   521   <a href="#networkservice">NetworkService</a>? <a href="#dom-networkservices-getservicebyid">getServiceById</a>(DOMString id);
   522 
   523   readonly attribute unsigned long    <a href="#dom-networkservices-servicesavailable">servicesAvailable</a>;
   524 
   525   // event handler attributes
   526            attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler" class="externalDFN">EventHandler</a>     <a href="#dom-networkservices-onserviceavailable">onserviceavailable</a>;
   527            attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler" class="externalDFN">EventHandler</a>     <a href="#dom-networkservices-onserviceunavailable">onserviceunavailable</a>;
   528 
   529 };
   530 
   531 <a href="#networkservices">NetworkServices</a> implements <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-eventtarget" class="externalDFN">EventTarget</a>;
   532 </pre>
   533 
   534       <section>
   535       <h2>Attributes</h2>
   536 
   537         <dl class="domintro">
   538           <dt>
   539             <code title="dom-networkservices-length">
   540               <a href="#dom-networkservices-length">length</a>
   541             </code>
   542           </dt>
   543           <dd>
   544             <p>
   545               Returns the current number of services in the respective object's <a>current authorized services</a>.
   546             </p>
   547           </dd>
   548           <dt>
   549             <code title="dom-networkservices-servicesavailable">
   550               <a href="#dom-networkservices-servicesavailable">servicesAvailable</a>
   551             </code>
   552           </dt>
   553           <dd>
   554             <p>
   555               Returns the current number of services matching one of the app-requested <a>valid service type</a> tokens that are actively available within the user's current network.
   556             </p>
   557           </dd>
   558         </dl>
   559 
   560         <div>
   561            <p>
   562               The <dfn id="dom-networkservices-length"><code>length</code></dfn> attribute MUST return the number of services represented in the object's corresponding <a>current authorized services</a> list at the time of getting.
   563            </p>
   564 
   565            <p>
   566               The <dfn id="dom-networkservices-servicesavailable"><code>servicesAvailable</code></dfn> attribute MUST return the number of services available in the
   567               user's network that match the <a>valid service type</a> that was initially used to create the current <a href="#networkservices"><code>NetworkServices</code></a> object.
   568            </p>
   569 
   570            <p>
   571              When a previously unknown instance of a networked service matching one of the requested <a href="#dfn-valid-service-type">valid service types</a> becomes available on the user's current network, the <a>user agent</a> MUST increment the <a href="#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute by <code>1</code> and then
   572              <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a>
   573              to dispatch a newly created event with the name <code>serviceavailable</code> that uses the <code>Event</code> interface, which does
   574              not bubble, is not cancellable, and has no default action, at the current <a href="#networkservices"><code>NetworkServices</code></a>
   575              object.
   576            </p>
   577 
   578            <p>
   579              When a previously known instance of a networked service matching one of the requested <a href="#dfn-valid-service-type">valid service types</a> becomes unavailable on the user's current network, the <a>user agent</a> MUST decrement the <a href="#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute by <code>1</code> and then
   580              <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a>
   581               to dispatch a newly created event with the name <code>serviceunavailable</code> that uses the <code>Event</code> interface, which does
   582               not bubble, is not cancellable, and has no default action, at the current <a href="#networkservices"><code>NetworkServices</code></a>
   583               object.
   584            </p>
   585         </div>
   586 
   587       </section>
   588 
   589       <section>
   590       <h2>Methods</h2>
   591         <dl class="domintro">
   592         <dt>
   593           <code title="networkservices-getter">
   594             <a href="#networkservices">services</a>
   595           </code>
   596           [
   597           <var title="">index</var>
   598           ]
   599         </dt>
   600         <dd>
   601           <p>
   602             Returns the specified <a href="#networkservice"><code>NetworkService</code></a> object.
   603           </p>
   604         </dd>
   605         <dt>
   606           <code title="networkservices-getter">
   607             <a href="#networkservices">services</a>
   608           </code>
   609           .
   610           <code title="dom-networkservices-getservicebyid">
   611             <a href="#dom-networkservices-getservicebyid">getServiceById</a>
   612           </code>
   613           (
   614           <var title="">id</var>
   615           )
   616         </dt>
   617         <dd>
   618           <p>
   619             Returns the <a href="#networkservice"><code>NetworkService</code></a> object with the given identifier, or null if no
   620             service has that identifier.
   621           </p>
   622         </dd>
   623       </dl>
   624 
   625       <p>
   626         A <a href="#networkservices"><code>NetworkServices</code></a> object represents the current list of zero or more <a>current authorized services</a>, of which zero or more can be available at a time. Each item in <a>current authorized services</a> is represented by a <a href="#networkservice"><code>NetworkService</code></a> object. The list of <a>current authorized services</a> is <span>immutable</span> meaning that it cannot be modified for the lifetime of a <a href="#networkservices"><code>NetworkServices</code></a> object.
   627       </p>
   628 
   629       <p class="note">
   630         Each service in a <a href="#networkservices"><code>NetworkServices</code></a> object thus has an index; the first has the index 0, and each subsequent service is numbered one higher than the previous one. If the <a>user agent</a> dynamically adds or removes network services for any reason, then the indices of the services in <a>current authorized services</a> will change dynamically. If the set of network services changes entirely, then all the previous services will be removed from <a>current authorized services</a> and replaced with new services.
   631       </p>
   632 
   633       <p>
   634         The <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#supported-property-indices" class="externalDFN">supported property indices</a> of <a href="#networkservices"><code>NetworkServices</code></a> objects at any instant are the numbers from zero to the number of items in <a>current authorized services</a> represented by the respective object minus one, if any services are represented in <a>current authorized services</a>. If a <a href="#networkservices"><code>NetworkServices</code></a> object represents no <a>current authorized services</a>, it has no <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#supported-property-indices" class="externalDFN">supported property indices</a>.
   635       </p>
   636 
   637       <p>
   638         To <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#determine-the-value-of-an-indexed-property" class="externalDFN">determine the value of an indexed property</a> for a given index <var>index</var> in a <a href="#networkservices"><code>NetworkServices</code></a> object's <a>current authorized services</a>, the user agent MUST return the <a href="#networkservice"><code>NetworkService</code></a> object that represents the <var>index</var>th service in <a>current authorized services</a>.
   639       </p>
   640 
   641       <p>
   642         The <dfn id="dom-networkservices-getservicebyid"><code>getServiceById(id)</code></dfn> method MUST return the first <a href="#networkservice"><code>NetworkService</code></a> object in <a>current authorized services</a> represented by the respective object whose <a href="#dom-networkservice-id"><code>id</code></a> attribute is equal to the value of the <var>id</var> argument.
   643         When no services in <a>current authorized services</a> match the given argument, the method MUST return null.
   644       </p>
   645 
   646       <p>
   647          Services available within the local network can connect and disconnect at different times during the execution of a web page. A <a>user agent</a> can
   648          inform a web page when the state of networked services matching the requested <a>valid service type</a> change. Web pages can use this information to enable in-page experiences for communicating the state of networked services
   649          with the ability to change the particular service or set of services the page is connected to by re-invoking the <a href="#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a> method.
   650       </p>
   651 
   652       </section>
   653 
   654       <section>
   655       <h2>Events</h2>
   656 
   657       <p>
   658          The following are the event handlers (and their corresponding event handler event types) that must be supported, as IDL attributes, by all objects implementing the <a href="#networkservices"><code>NetworkServices</code></a> interface:
   659        </p>
   660 
   661        <table border="1">
   662         <thead>
   663           <tr>
   664             <th>
   665               <span title="event handlers">Event handler</span>
   666             </th>
   667             <th>
   668               <span>Event handler event type</span>
   669             </th>
   670           </tr>
   671         </thead>
   672         <tbody>
   673           <tr>
   674             <td>
   675               <dfn id="dom-networkservices-onserviceavailable" title="dom-NetworkServices-onserviceavailable">
   676                 <code>onserviceavailable</code>
   677               </dfn>
   678             </td>
   679             <td>
   680               <code title="event-serviceavailable">serviceavailable</code>
   681             </td>
   682           </tr>
   683           <tr>
   684             <td>
   685               <dfn id="dom-networkservices-onserviceunavailable" title="dom-NetworkServices-onserviceunavailable">
   686                 <code>onserviceunavailable</code>
   687               </dfn>
   688             </td>
   689             <td>
   690               <code title="event-serviceunavailable">serviceunavailable</code>
   691             </td>
   692           </tr>
   693         </tbody>
   694       </table>
   695 
   696       <p>
   697          Events with an event type of <code>serviceavailable</code> or <code>serviceunavailable</code> defined in this specification are simple <code>Event</code> objects.
   698       </p>
   699 
   700       </section>
   701 
   702     </section>
   703     <section>
   704     <h2>Communicating with a networked service</h3>
   705 
   706 <p>
   707    The <a href="#networkservice"><code>NetworkService</code></a> interface is used to provide a set of connection information for an HTTP service endpoint and if available, service events, running on a networked device.
   708 </p>
   709 
   710 <pre class="widl">
   711 [NoInterfaceObject]
   712 interface <dfn id="networkservice">NetworkService</dfn> {
   713   readonly attribute DOMString        <a href="#dom-networkservice-id">id</a>;
   714   readonly attribute DOMString        <a href="#dom-networkservice-name">name</a>;
   715   readonly attribute DOMString        <a href="#dom-networkservice-type">type</a>;
   716   readonly attribute DOMString        <a href="#dom-networkservice-url">url</a>;
   717   readonly attribute DOMString        <a href="#dom-networkservice-config">config</a>;
   718 
   719   readonly attribute boolean          <a href="#dom-networkservice-online">online</a>;
   720 
   721   // event handler attributes
   722            attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler" class="externalDFN">EventHandler</a>     <a href="#dom-networkservice-onserviceonline">onserviceonline</a>;
   723            attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler" class="externalDFN">EventHandler</a>     <a href="#dom-networkservice-onserviceoffline">onserviceoffline</a>;
   724 
   725            attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler" class="externalDFN">EventHandler</a>     <a href="#dom-networkservice-onnotify">onnotify</a>;
   726 };
   727 
   728 <a href="#networkservice">NetworkService</a> implements <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-eventtarget" class="externalDFN">EventTarget</a>;
   729 </pre>
   730 
   731 <section>
   732   <h2>Attributes</h2>
   733 
   734       <dl class="domintro">
   735         <dt>
   736           <var title="">service</var>
   737            .
   738           <code title="dom-networkservice-id">
   739             <a href="#dom-networkservice-id">id</a>
   740           </code>
   741         </dt>
   742         <dd>
   743           <p>
   744             A unique identifier for the given user-selected service instance.
   745           </p>
   746         </dd>
   747         <dt>
   748           <var title="">service</var>
   749            .
   750           <code title="dom-networkservice-name">
   751             <a href="#dom-networkservice-name">name</a>
   752           </code>
   753         </dt>
   754         <dd>
   755           <p>
   756             The name of the user-selected service.
   757           </p>
   758         </dd>
   759         <dt>
   760           <var title="">service</var>
   761            .
   762           <code title="dom-networkservice-type">
   763             <a href="#dom-networkservice-type">type</a>
   764           </code>
   765         </dt>
   766         <dd>
   767           <p>
   768             The <a>valid service type</a> token value of the user-selected service.
   769           </p>
   770         </dd>
   771         <dt>
   772           <var title="">service</var>
   773            .
   774           <code title="dom-networkservice-url">
   775             <a href="#dom-networkservice-url">url</a>
   776           </code>
   777         </dt>
   778         <dd>
   779           <p>
   780             The control URL endpoint (including any required port information) of the user-selected control service that has been added to the <a>entry script origin's URL whitelist</a>.
   781           </p>
   782         </dd>
   783         <dt>
   784           <var title="">service</var>
   785            .
   786           <code title="dom-networkservice-config">
   787             <a href="#dom-networkservice-config">config</a>
   788           </code>
   789         </dt>
   790         <dd>
   791           <p>
   792             The configuration information associated with the service depending on the requested service type.
   793           </p>
   794         </dd>
   795       </dl>
   796 
   797           <p>
   798             The <dfn id="dom-networkservice-id"><code>id</code></dfn> attribute is a unique identifier for the service. Two services provided at different times or on different objects MUST have the same <a href="#dom-networkservice-id"><code>id</code></a> value.
   799          </p>
   800 
   801          <p>
   802             The <dfn id="dom-networkservice-name"><code>name</code></dfn> attribute represents a human-readable title for the service.
   803          </p>
   804 
   805          <p>
   806              The <dfn id="dom-networkservice-type"><code>type</code></dfn> attribute reflects the value of the <a>valid service type</a> of the service.
   807           </p>
   808 
   809          <p>
   810             The <dfn id="dom-networkservice-url"><code>url</code></dfn> attribute is an <a href="http://www.w3.org/TR/html5/urls.html#absolute-url" class="externalDFN">absolute URL</a> pointing to the root HTTP
   811             endpoint for the service that has been added to the <a>entry script origin's URL whitelist</a>. Web pages can subsequently use this value for implicit cross-document messaging via various existing mechanisms (e.g. Web Sockets, Server-Sent Events, Web Messaging, XMLHttpRequest).
   812          </p>
   813 
   814          <p>
   815             The <dfn id="dom-networkservice-config"><code>config</code></dfn> attribute provides the raw configuration information extracted from the given network service.
   816          </p>
   817 
   818       </section>
   819 
   820       <section>
   821          <h3>States</h3>
   822 
   823       <dl class="domintro">
   824         <dt>
   825           <var title="">service</var>
   826            .
   827           <code title="dom-networkservice-online">
   828             <a href="#dom-networkservice-online">online</a>
   829           </code>
   830         </dt>
   831         <dd>
   832           <p>
   833             Returns <code>true</code> if the service is reporting that it is accessible on the local network or <code>false</code> if the service is reporting that it is no longer accessible (temporarily or permanently) on the local network.
   834           </p>
   835         </dd>
   836       </dl>
   837 
   838       <p>
   839         The <dfn id="dom-networkservice-online"><code>online</code></dfn> attribute indicates whether the service is reporting itself as being
   840         either <var>online</var>, and therefore accessible on the local network, in which case this attribute will return <code>true</code> or, <var>offline</var>, and therefore not accessible on the local network, either temporarily or permanently, in which case this attribute will return <code>false</code>. This attribute MUST default to <code>true</code>.
   841       </p>
   842 
   843       </section>
   844 
   845       <section>
   846          <h3>Events</h3>
   847 
   848       <p>
   849          The following are the event handlers (and their corresponding event handler event types) that must be supported, as IDL attributes, by all objects implementing the
   850          <a href="#networkservice"><code>NetworkService</code></a> interface:
   851        </p>
   852 
   853        <table border="1">
   854         <thead>
   855           <tr>
   856             <th>
   857               <span title="event handlers">Event handler</span>
   858             </th>
   859             <th>
   860               <span>Event handler event type</span>
   861             </th>
   862           </tr>
   863         </thead>
   864         <tbody>
   865           <tr>
   866             <td>
   867               <dfn id="dom-networkservice-onnotify" title="dom-NetworkService-onnotify">
   868                 <code>onnotify</code>
   869               </dfn>
   870             </td>
   871             <td>
   872               <code title="event-notify">notify</code>
   873             </td>
   874           </tr>
   875           <tr>
   876             <td>
   877               <dfn id="dom-networkservice-onserviceonline" title="dom-NetworkService-onserviceonline">
   878                 <code>onserviceonline</code>
   879               </dfn>
   880             </td>
   881             <td>
   882               <code title="event-onserviceonline">serviceonline</code>
   883             </td>
   884           </tr>
   885           <tr>
   886             <td>
   887               <dfn id="dom-networkservice-onserviceoffline" title="dom-NetworkService-onserviceoffline">
   888                 <code>onserviceoffline</code>
   889               </dfn>
   890             </td>
   891             <td>
   892               <code title="event-onserviceoffline">serviceoffline</code>
   893             </td>
   894           </tr>
   895         </tbody>
   896       </table>
   897 
   898       <p>
   899          Events with an event type of <code>notify</code>, <code>serviceonline</code> or <code>serviceoffline</code> defined in this specification are simple <code>Event</code> objects.
   900       </p>
   901 
   902       </section>
   903    </section>
   904 
   905       <section>
   906             <h2>Service Discovery</h2>
   907 
   908       <p>
   909          A <a>user agent</a> conforming to this specification MAY implement <acronym title="Simple Service Discovery Protocol">SSDP</acronym> [[!UPNP-DEVICEARCH11]] and Zeroconf [[!DNS-SD]] + [[!MDNS]] service discovery mechanisms
   910          to enable Web pages to request and connect with HTTP services running on networked devices, discovered via either mechanism, through this API. When a <a>user agent</a> implements either of these service discovery mechanisms, then it MUST conform to the corresponding algorithms provided in this section of the specification.
   911       </p>
   912       <p>
   913          This section presents how the results of these two service discovery
   914          mechanisms will be matched to requested service types and how their properties will be applied to any resulting <a href="#networkservice"><code>NetworkService</code></a> objects.
   915       </p>
   916 
   917       <p>
   918          It is expected that user agents will perform these service discovery mechansisms asynchronously and periodically update the <a>list of networked devices</a> as required. The timing of any
   919          service discovery mechanisms is an implementation detail left to the discretion of the implementer (e.g. once on user agent start-up, every X seconds during user agent execution or on
   920          invocation of this API from a Web page).
   921       </p>
   922 
   923       <p>
   924          The <dfn>list of available service records</dfn> is a single dynamic internal lookup table within user agents that is used to track the current services available in the network at any given time.
   925          At any point during the running of either of the two service discovery mechanisms then existing entries within this table can be updated, entries can be added and entries can be removed as the status of networked
   926          services changes. Each record contained within this table contains the attributes: <code>id</code>, <code>name</code>, <code>type</code>, <code>url</code> and <code>config</code>.
   927       </p>
   928 
   929             <section>
   930          <h4>Zeroconf (<abbr title="Multicast DNS">mDNS</abbr> + <abbr title="Domain Name System">DNS</abbr>-<abbr title="Service Discovery">SD</abbr>)</h4>
   931 
   932          <p>
   933             For each DNS response received from a user-agent-initiated Multicast DNS Browse for <abbr title="DNS Pointer Record">PTR</abbr> records with the name <code>_services._dns-sd._udp</code> on the resolved recommended automatic browsing
   934    domain [[!MDNS]], the <a>user agent</a> MUST run the following steps:
   935          </p>
   936 
   937          <ol class="rule">
   938 
   939             <li>Let <var>service mDNS responses</var> be an array of PTR records received by issuing a Multicast DNS Browse for PTR records with the name of the current discovered service type.</li>
   940 
   941             <li>For each Object <var>service mDNS response</var> in <var>service mDNS responses</var>, run the following steps:
   942                <ol>
   943 
   944                   <li>
   945                      Let <var>network service record</var> be an Object consisting of the following empty properties: <code>id</code>, <code>name</code>, <code>type</code>, <code>url</code>, <code>config</code>.
   946                   </li>
   947 
   948                   <li>
   949                      Set <var>network service record</var>'s <code>id</code> property to the value of the full PTR Service Instance Name [[!MDNS]].
   950                   </li>
   951 
   952                   <li>
   953                      Set <var>network service record</var>'s <code>name</code> property to the value of the PTR Service Instance Name's <var>Instance</var> component [[!MDNS]].
   954                   </li>
   955 
   956                   <li>
   957                      Set <var>network service record</var>'s <code>type</code> property to the concatenation of the string <code>zeroconf:</code> followed by the value of the PTR Service Instance Name's <var>Service</var> component [[!MDNS]].
   958                   </li>
   959 
   960                   <li>
   961                      Set <var>network service record</var>'s <code>url</code> property to the resolvable Service URL obtained from performing an DNS-SD Lookup [[!DNS-SD]] of the current service from the PTR record provided [[!MDNS]].
   962                   </li>
   963 
   964                   <li>
   965                      Set <var>network service record</var>'s <code>config</code> property to the string value of the contents of the first DNS-SD TXT record associated with the <var>service mDNS response</var> as defined in [[!DNS-SD]].
   966                   </li>
   967 
   968                   <li>
   969                      For each Object <var>existing service record</var> in the current <a>list of available service records</a>, run the following sub-steps:
   970                      <ol class="rule">
   971 
   972                        <li>
   973                         If the <var>existing service record</var>'s <code>id</code> property matches the value of the <var>network service record</var>'s <code>id</code>, then set the
   974                         value of <var>existing service record</var> in the current <a>list of available service records</a>  to the value of the
   975                         <var>network service record</var> and skip the next step.
   976                        </li>
   977                      </ol>
   978                   </li>
   979 
   980                   <li>
   981                      Add <var>network service record</var> to the <a>list of available service records</a>.
   982                   </li>
   983 
   984                   <li>
   985                      For each non-garbage collected <a href="#networkservice"><code>NetworkService</code></a> object run the following steps:
   986 
   987                      <ol class="rule">
   988                         <li>
   989                            If the <a href="#networkservice"><code>NetworkService</code></a> object's <code>type</code> attribute does not equal the
   990                            current <a>network service record</a>'s <code>type</code> property then continue at the next available active
   991                            <a href="#networkservice"><code>NetworkService</code></a> object.
   992                         </li>
   993                         <li>
   994                            Increment the <a href="#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute of the <a href="#networkservices"><code>NetworkServices</code></a> object by <code>1</code>.
   995                         </li>
   996                         <li>
   997                           <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">Queue a task</a>
   998                            to dispatch a newly created event with the name <code>serviceavailable</code> that uses the <code>Event</code> interface, which does not bubble, is not cancellable, and has no default action, at the current
   999                             <a href="#networkservices"><code>NetworkServices</code></a> object.
  1000                         </li>
  1001                         <li>
  1002                           <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">Queue a task</a>
  1003                            to dispatch a newly created event with the name <code>serviceonline</code> that uses the <code>Event</code> interface, which does not bubble, is not cancellable, and has no default action, at the current
  1004                            <a href="#networkservice"><code>NetworkService</code></a> object.
  1005                         </li>
  1006                      </ol>
  1007                   </li>
  1008             </ol>
  1009            </li>
  1010          </ol>
  1011 
  1012       </section>
  1013 
  1014       <section>
  1015          <h5>Universal Plug-and-Play (<abbr title="Universal Plug-and-Play">UPnP</abbr>)</h5>
  1016 
  1017          <p>
  1018             For each SSDP Presence Announcement [[!UPNP-DEVICEARCH11]] - a HTTP NOTIFY request - received from a user-agent-initiated SSDP Discovery Request [[!UPNP-DEVICEARCH11]], the <a>user agent</a> MUST run the following steps:
  1019          </p>
  1020 
  1021          <ol class="rule">
  1022             <li>
  1023                Let <var>ssdp device</var> be an Object with a property for each HTTP header received in the received SSDP Presence Announcement, with each key being the name of a HTTP header and its
  1024                value being that HTTP header's accompanying value.
  1025             </li>
  1026 
  1027             <li>
  1028                If <var>ssdp device</var> does not contain at least one <var>NTS</var>, <var>USN</var> and <var>Location</var> parameter, then the <a>user agent</a> MUST abort these steps.
  1029             </li>
  1030 
  1031             <li>
  1032                If the first occurrence of <var>NTS</var> has a value other than <code>ssdp:alive</code>, then continue to the step labeled <var>update service monitor</var> below.
  1033             </li>
  1034 
  1035             <li>
  1036                Let <var>root device descriptor file</var> contain the contents of the file located at the URL provided in the first occurrence of <var>Location</var> obtained according to the rules
  1037                defined in the section 'Retrieving a description using HTTP' [[!UPNP-DEVICEARCH11]].
  1038             </li>
  1039 
  1040             <li>
  1041                If <var>root device descriptor file</var> is empty, then the <a>user agent</a> MUST abort these steps.
  1042             </li>
  1043 
  1044             <li>
  1045                Let <var>advertised services</var> be a <a>list of all advertised services</a> obtained from the <var>root device descriptor file</var> containing all sub-nodes of the <code>serviceList</code> node as described in
  1046                the section 'Device Description' [[!UPNP-DEVICEARCH11]].
  1047             </li>
  1048 
  1049             <li>
  1050                For each Object <var>advertised service</var> in <var>advertised services</var> run the following steps:
  1051                <ol class="rule">
  1052 
  1053                   <li>
  1054                      Let <var>network service record</var> be an Object consisting of the following empty properties: <code>id</code>, <code>name</code>, <code>type</code>, <code>url</code>, <code>eventsUrl</code>, <code>config</code>.
  1055                   </li>
  1056 
  1057                   <li>
  1058                      Set <var>network service record</var>'s <code>id</code> property to the string value of the first occurrence of <var>ssdp device</var>'s <var>USN</var> parameter.
  1059                   </li>
  1060 
  1061                   <li>
  1062                      Set <var>network service record</var>'s <code>name</code> property to the string value of the first occurrence of the <var>service</var>'s <code>serviceId</code> property.
  1063                   </li>
  1064 
  1065                   <li>
  1066                      Set <var>network service record</var>'s <code>type</code> property to the concatenation of the string <code>upnp:</code> followed by the string value of the first occurrence of the <var>service</var>'s <code>serviceType</code> property.
  1067                   </li>
  1068 
  1069                   <li>
  1070                      Set <var>network service record</var>'s <code>url</code> property to the string value of the first occurrence of the <var>service</var>'s <code>controlURL</code> property.
  1071                   </li>
  1072 
  1073                   <li>
  1074                      Set <var>network service record</var>'s <code>config</code> property to the string value of the first occurrence of the <var>device</var> property.
  1075                   </li>
  1076 
  1077                   <li>
  1078                      If <var>service</var>'s <code>eventSubURL</code> property is empty, then continue to the step labeled <em>register</em> below.
  1079                   </li>
  1080 
  1081                   <li>
  1082                      Set <var>network service record</var>'s <code>eventsUrl</code> property to the string value of the first occurrence of the <var>service</var>'s <code>eventSubURL</code> property.
  1083                   </li>
  1084 
  1085                   <li>
  1086                      <em>Register</em>: For each Object <var>existing service record</var> in the current <a>list of available service records</a>, run the following sub-steps:
  1087                      <ol class="rule">
  1088 
  1089                        <li>
  1090                         If the <var>existing service record</var>'s <var>id</var> property matches the value of the first occurrence of <var>USN</var> and the
  1091                         <var>existing service record</var>'s <code>type</code> property matches the value of <var>network service record</var>'s <code>type</code>, then set the
  1092                         value of <var>existing service record</var> in the current <a>list of available service records</a>  to the value of the
  1093                         <var>network service record</var> and skip the next step.
  1094                        </li>
  1095                      </ol>
  1096                   </li>
  1097 
  1098                   <li>
  1099                      Add <var>network service record</var> to the <a>list of available service records</a>.
  1100                   </li>
  1101 
  1102                </ol>
  1103             </li>
  1104             <li>
  1105                <em>Update Service Monitor</em>: For each non-garbage collected <a href="#networkservice"><code>NetworkService</code></a> object run the following steps:
  1106 
  1107                <ol class="rule">
  1108                   <li>
  1109                      If this <a href="#networkservice"><code>NetworkService</code></a> object's <code>type</code> attribute does not equal the
  1110                      current <a>network service record</a>'s <code>type</code> property then continue at the next available active
  1111                      <a href="#networkservice"><code>NetworkService</code></a> object.
  1112                   </li>
  1113                   <li>
  1114                      If the <var>announcement type</var> equals <code>ssdp:alive</code> then increment the <a href="#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute of the <a href="#networkservices"><code>NetworkServices</code></a>
  1115                      object by <code>1</code> and then <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a>
  1116                       to dispatch a newly created event with the name <code>serviceavailable</code> that uses the <code>Event</code> interface, which does not bubble, is not cancellable, and has no default action, at the current
  1117                       <a href="#networkservice"><code>NetworkServices</code></a> object. Otherwise, decrement the <a href="#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute of the <a href="#networkservices"><code>NetworkServices</code></a>
  1118                      object by <code>1</code> and then  <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a>
  1119                        to dispatch a newly created event with the name <code>serviceunavailable</code> that uses the <code>Event</code> interface, which does not bubble, is not cancellable, and has no default action, at the current
  1120                        <a href="#networkservice"><code>NetworkServices</code></a> object.
  1121                   </li>
  1122                   <li>
  1123                      If the <var>announcement type</var> equals <code>ssdp:alive</code> then <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a>
  1124                       to dispatch a newly created event with the name <code>serviceonline</code> that uses the <code>Event</code> interface, which does not bubble, is not cancellable, and has no default action, at the current
  1125                       <a href="#networkservice"><code>NetworkService</code></a> object. Otherwise, <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">queue a task</a>
  1126                        to dispatch a newly created event with the name <code>serviceoffline</code> that uses the <code>Event</code> interface, which does not bubble, is not cancellable, and has no default action, at the current
  1127                        <a href="#networkservice"><code>NetworkService</code></a> object.
  1128                   </li>
  1129                </ol>
  1130             </li>
  1131          </ol>
  1132 
  1133          <p>
  1134             A <dfn>user-agent generated callback url</dfn> is a Local-network accessible URL endpoint that a <a>user agent</a> must generate and maintain for receiving HTTP NOTIFY requests from UPnP Event sources.
  1135          </p>
  1136 
  1137          <p>When the <a>user agent</a> is to <dfn>setup a UPnP Events Subscription</dfn>, it is to run the following steps with the current <var>network service record</var> object:</p>
  1138 
  1139          <ol class="rule">
  1140             <li>
  1141                If <var>network service record</var>'s <code>eventsUrl</code> property is empty then the <a>user agent</a> MUST abort these steps.
  1142             </li>
  1143 
  1144             <li>
  1145                Let <var>callback URL</var> be the value of creating a new <a>user-agent generated callback url</a>.
  1146             </li>
  1147 
  1148             <li>
  1149                Send a HTTP SUBSCRIBE request with a <em>NT</em> header with a string value of <code>upnp:event</code>, a <em>TIMEOUT</em> header with an integer value ofÆ’
  1150                <code>86400</code> and a <em>CALLBACK</em> header
  1151                with a string value of <var>callback URL</var> towards the <var>network service record</var>'s <code>eventsUrl</code> property.
  1152             </li>
  1153 
  1154             <li>
  1155                If a non-200 OK response is received from the HTTP SUBSCRIBE request then the <a>user agent</a> MUST abort these steps.
  1156             </li>
  1157 
  1158             <li>
  1159                On receiving a valid 200 OK response, run the following steps:
  1160 
  1161                <ol class="rule">
  1162                   <li>
  1163                      Let <var>callback ID</var> equal the string value of the first included <em>SID</em> header, if it exists.
  1164                   </li>
  1165                   <li>
  1166                      Let <var>timeout date</var> equal the sum of the current UTC date value plus the integer value of the first included <em>TIMEOUT</em> header, if it exists.
  1167                   </li>
  1168                   <li>
  1169                      Run the following steps aynchronously and continue to the step labeled <em>listen</em> below.
  1170                   </li>
  1171                   <li>
  1172                      <em>Refresh Subscription</em>: Run the following steps at a set interval (X) within the <a>user agent</a>:
  1173 
  1174                      <ol class="rule">
  1175                         <li>
  1176                            Let <var>current date</var> equal the current UTC date.
  1177                         </li>
  1178                         <li>
  1179                            If <var>current date</var> is less than the <var>timeout date</var> then continue to the step labeled <em>refresh subscription</em> above.
  1180                         </li>
  1181                         <li>
  1182                            Send a HTTP SUBSCRIBE request with a <em>SID</em> header with the string value of <var>callback ID</var> and a <em>TIMEOUT</em> header
  1183                            with an integer value of <code>86400</code> towards the <var>network service record</var>'s <code>eventsUrl</code> property.
  1184                         </li>
  1185                         <li>
  1186                            On receiving a valid 200 OK, update <var>callback ID</var> with the string value of the first included <em>SID</em> header, if it exists. All other HTTP
  1187                            responses should cause the <a>user agent</a> to continue from the step labeled <em>refresh subscription</em> above.
  1188                         </li>
  1189                      </ol>
  1190 
  1191                   </li>
  1192 
  1193                   <li>
  1194                      <em>Listen</em>: For each HTTP NOTIFY request received at the <var>callback URL</var> the <a>user agent</a> is to run the following steps:
  1195 
  1196                      <ol class="rule">
  1197                         <li>
  1198                            Let <var>content clone</var> be the result of obtaining the message body of the HTTP NOTIFY request. If <var>content clone</var> is empty, then the <a>user agent</a> MUST abort these steps.
  1199                         </li>
  1200                         <li>
  1201                           Let <var>notification event</var> be a new simple event that uses the <code>Event</code> interface with the name <code>notify</code>,
  1202                            which does not bubble, is not cancellable, and has no default action.
  1203                         </li>
  1204                         <li>
  1205                            Let the <code>data</code> attribute of <var>notification event</var> have the DOMString value of <var>content clone</var>.
  1206                         </li>
  1207                         <li>
  1208                            <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">Queue a task</a> to
  1209                             dispatch <var>notification event</var> at the current <a><code>NetworkService</code></a> object.
  1210                         </li>
  1211                      </ol>
  1212                   </li>
  1213 
  1214                </ol>
  1215 
  1216             </li>
  1217          </ol>
  1218 
  1219          </section>
  1220 
  1221          <section>
  1222             <h3>Network Topology Monitoring</h3>
  1223 
  1224                   <div>
  1225                      <p>
  1226                         When the <a>user agent</a> detects that the user has dropped from their connected network, then it MUST run the following steps:
  1227                      </p>
  1228 
  1229                      <ol class="rule">
  1230                         <li>
  1231                            Flush all entries from the <a>list of available service records</a>.
  1232                         </li>
  1233                         <li>
  1234                            For each <a href="#networkservice"><code>NetworkService</code></a> object currently active in the <a>user agent</a> perform the following steps:
  1235 
  1236                            <ol class="rule">
  1237                               <li>
  1238                                  Set the <a href="#dom-networkservice-online"><code>online</code></a> attribute to <code>false</code>.
  1239                               </li>
  1240                               <li>
  1241                                  <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task" class="externalDFN">Queue a task</a>
  1242                                                       to dispatch a newly created event with the name <code>serviceoffline</code> that uses the <code>Event</code> interface, which does not bubble, is not cancellable, and has no default action, at the current
  1243                                                       <a href="#networkservice"><code>NetworkService</code></a> object.
  1244                            </ol>
  1245                         </li>
  1246                         <li>
  1247                           For each <a href="#networkservices"><code>NetworkServices</code></a> object currently active in the <a>user agent</a> perform the following steps:
  1248 
  1249                           <ol class="rule">
  1250                             <li>
  1251                               Let <var>number of available services</var> equal the value of <a href="#networkservices"><code>NetworkServices</code></a>'s <a href="#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute.
  1252                             </li>
  1253                             <li>
  1254                               Set the <a href="#networkservices"><code>NetworkServices</code></a>'s <a href="#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute to zero (<code>0</code>).
  1255                             </li>
  1256                             <li>
  1257                               For each <var>available service</var> in <var>number of available services</var> the <a>user agent</a> MUST fire a new simple event with the name <code>serviceunavailable</code> that has no default action, does not bubble and is not cancellable, at the current <a href="#networkservices"><code>NetworkServices</code></a> object.
  1258                             </li>
  1259                           </ol>
  1260                         </li>
  1261 
  1262                      </ol>
  1263 
  1264                      <p>
  1265                         When the <a>user agent</a> detects that the user has connected to a new network, then it SHOULD run the following steps:
  1266                      </p>
  1267 
  1268                      <ol class="rule">
  1269                         <li>
  1270                            Re-issue an mDNS search and SSDP discovery search using all of the <a>valid service type</a> tokens initially provided to all active <a href="#networkservices"><code>NetworkServices</code></a> objects and handle all discovery responses according to the processing defined in <a href="#service-discovery">Section 7: Service Discovery</a>.
  1271                         </li>
  1272                      </ol>
  1273                   </div>
  1274          </section>
  1275       </section>
  1276 
  1277    <section>
  1278       <h3>Garbage collection</h3>
  1279 
  1280       <p>
  1281          A <a><code>NetworkService</code></a> object containing a <code>url</code> parameter currently in the <a>entry script origin's URL whitelist</a> MUST NOT be garbage collected.
  1282       </p>
  1283 
  1284       <p>
  1285          Only when the user navigates away from the current browsing context can <a><code>NetworkService</code></a> objects be garbage-collected and records in the <a>entry script origin's URL whitelist</a> be removed.
  1286       </p>
  1287 
  1288    </section>
  1289 
  1290 
  1291     <section>
  1292       <h3>Use Cases and Requirements</h3>
  1293 
  1294       <p>This section covers what the requirements are for this API, as well as illustrates some use cases.</p>
  1295 
  1296       <ul class="rule">
  1297          <li>
  1298             Once a user has given permission, user agents should provide the ability for Web pages to communicate directly with a Local-networked Service.
  1299             <ul class="rule">
  1300                <li>
  1301                   Example: A web-based TV remote control. A Web page wants to control the current user's TV, changing the programming shown or increasing/decreasing/muting the
  1302                   volume of the Local-networked Device. The Web page requests a service type that is known to be implemented by television sets to which it has the
  1303                   application logic to communicate. Local devices providing the request service types are discovered and presented to the user for authorization. The user selects one
  1304                   or more of the discovered television sets to be accessible to the current Web page and then clicks 'Share'. The Web page can now communicate directly with
  1305                   the user-authorized Local-networked services.
  1306                </li>
  1307             </ul>
  1308          </li>
  1309 
  1310          <li>
  1311            Web pages should be able to communicate with Local-networked Services using the messaging channel supported by those Devices.
  1312            <ul class="rule">
  1313             <li>
  1314                Example: A Web page advertises that it is capable of controlling multiple Home Media Servers. The user can select their Home Media Server type from a drop-down list, at which point the
  1315                Web page sends a request to the user agent to connect with the associated service type of the Home Media Server. The Media Server selected implements a Web Socket channel for
  1316                bi-directional service communication and so the Web page opens a web socket to the requested Media Server and can communicate as required via that appropriate channel.
  1317             </li>
  1318            </ul>
  1319          </li>
  1320 
  1321          <li>
  1322            Web pages should be able to communicate with Local-networked Services using the messaging format supported by those Devices.
  1323            <ul class="rule">
  1324             <li>
  1325                Example: A Web page advertises that it is capable of interacting with and controlling multiple types of Home Media Server. The user can select their Home Media Server type from a drop-down list or known Media Servers, at which point the
  1326                Web page sends a request to the user agent to connect with the associated service type (and, optionally, the associated event type) of the Home Media Server. The communiciation protocols supported by Home Media Servers typically vary
  1327                between UPnP, JSON-RPC, Protocol Buffers or other messaging formats depending on the Home Media Server requested. The Web page is able to communicate with the user-selected Home Media
  1328                Server in the messaging format supported by that Device, which, in this example is a simple key/value pair text format.
  1329             </li>
  1330            </ul>
  1331          </li>
  1332 
  1333          <li>
  1334            Web pages should not be able to communicate with Local-networked Services that have not been authorized by the user thereby maintaining the user's privacy.
  1335            <ul class="rule">
  1336             <li>
  1337                Example: A Web page requests access to one type of Local-networked service. The user authorizes access to that particular service. Other services running on that same device, and on other devices
  1338                within the network, should not be accessible to the current Web page.
  1339             </li>
  1340            </ul>
  1341          </li>
  1342 
  1343          <li>
  1344            A user should be able to share one or more Local-networked Services based on a particular service type request from a Web page.
  1345            <ul class="rule">
  1346             <li>
  1347                Example: A Web page is capable of interacting with a specific profile of Local-networked Service. As such, it makes a request to the user agent to access those services, of which multiple matches
  1348                are found. The user is capable of selecting one or more of the discovered services to share with the Web page. The Web page can then implement a drag-and-drop interface for the user to drag specific
  1349                actions on to one or more of the authorized Local-networked Services.
  1350             </li>
  1351            </ul>
  1352          </li>
  1353 
  1354          <li>
  1355            User agents should provide an API exposed to script that exposes the features above. The user is notified by UI anytime interaction with Local-networked Services is requested, giving the user
  1356            full ability to cancel or abort the transaction. The user selects the Local-networked Services to be connected to the current Web page, and can cancel these at any time. No invocations to
  1357            these APIs occur silently without user intervention.
  1358          </li>
  1359       </ul>
  1360     </section>
  1361 
  1362           <section class="informative appendix">
  1363              <h3>Examples</h3>
  1364 
  1365            <div class="example">
  1366             <p>This sample code exposes a button. When clicked, this button is disabled and the user is prompted to offer a network service. The user may also select multiple network services. When the user has authorized a network service to be connected to the web page then the web page issues a simple command to get a list of all the albums stored on the connected media player service.
  1367             <p>The button is re-enabled only when the connected network service disconnects for whatever reason (the service becomes unavailable on the network, the user disconnects from their current network or the user revokes access to the service from the current web page). At this point the user can re-click the button to select a new network service to connect to the web page and the above steps are repeated.</p>
  1368             <p>The provided service type identifier and service interaction used in this example is based on the well-defined service type and messaging format supported by the <a href="http://xbmc.org/about/">XBMC Media Server</a>. </p>
  1369             <hr />
  1370             <pre class="highlight">&lt;input type="button" value="Start" onclick="start()" id="startBtn"/&gt;
  1371 &lt;div id="debugconsole">&lt;/div>
  1372 
  1373 &lt;script>
  1374  var startBtn = document.getElementById('startBtn'),
  1375      debug = document.getElementById('debugconsole');
  1376 
  1377  function start() {
  1378    if(navigator.getNetworkServices) {
  1379       navigator.getNetworkServices('zeroconf:_xbmc-jsonrpc._tcp', gotXBMCService, error);
  1380       startBtn.disabled = true;
  1381    } else {
  1382       debug.innerHTML += "&lt;br&gt;Service Discovery not supported!";
  1383    }
  1384  }
  1385 
  1386  function gotXBMCService(services) {
  1387 
  1388 // Listen for service disconnect messages
  1389 
  1390    services[0].addEventListener('serviceoffline', function ( e ) {
  1391        debug.innerHTML += "&lt;br>" + services[0].name + " disconnected.";
  1392        startBtn.disabled = false;
  1393    }, false);
  1394 
  1395 // Send a service message to get albums list (and process the service response)
  1396 
  1397    var svcXhr = new XMLHttpRequest();
  1398    svcXhr.open("POST", services[0].url + "/getAlbums"); // services[0].url and its subresources have been
  1399                                                         // whitelisted for cross-site XHR use in this
  1400                                                         // current browsing context.
  1401 
  1402    svcXhr.setRequestHeader('Content-Type', 'application/json-rpc');
  1403 
  1404    svcXhr.addEventListener('readystatechange', function ( response ) {
  1405      if( response.readyState != 4 || response.status != 200 )
  1406         return;
  1407      debug.innerHTML += "&lt;br>" + services[0].name + " response received: ";
  1408      debug.textContent += JSON.parse(response.responseText);
  1409    }, false);
  1410 
  1411    var svcMsg = [
  1412      { "jsonrpc": "2.0", "method": "AudioLibrary.GetAlbums", "params": { "genreid": -1,
  1413          "artistid": -1, "start": -1, "end": -1 }, "id": "1" }
  1414    ];
  1415 
  1416    svcXhr.send(JSON.stringify(svcMsg));
  1417    debug.innerHTML += "&lt;br>" + services[0].name + " request sent: ";
  1418    debug.textContent += JSON.stringify(svcMsg);
  1419 
  1420  }
  1421 
  1422  function error( err ) {
  1423    debug.innerHTML += "&lt;br>An error occurred obtaining a local network service.";
  1424    startBtn.disabled = false;
  1425  }
  1426 &lt;/script></pre>
  1427            </div>
  1428 
  1429            <div class="example">
  1430             <p>
  1431              This sample exposes a drop-down list containing a number of common Home-based audio devices. When the user selects an audio device from the list provided, they are prompted to authorize a network service
  1432              based on the service type requested. The user may also select multiple network services matching the selected service type.
  1433              In this example, the user selects their make as being <var>Sony</var> and their model as being <var>Bravia S1000</var> from which the Web page can derive a service type
  1434              (<var>urn:schemas-upnp-org:service:RenderingControl:1</var>).
  1435              <br /><br />Once the user has authorized the device, the web page sends a simple mute command according to the messaging format supported by the device.
  1436             </p>
  1437             <hr />
  1438             <pre class="highlight">&lt;select name="make" id="make"&gt;
  1439   &lt;option selected="selected" disabled="disabled"&gt;Select make&lt;/option&gt;
  1440   &lt;option&gt;Sony&lt;/option&gt;
  1441   &lt;option&gt;Philips&lt;/option&gt;
  1442   &lt;option&gt;Alba&lt;/option&gt;
  1443 &lt;/select&gt;
  1444 &lt;select name="model" id="model"&gt;&lt;/select&gt;
  1445 &lt;div id="debugconsole"&gt;&lt;/div&gt;
  1446 
  1447 &lt;script&gt;
  1448   var debug = document.getElementById('debugconsole');
  1449 
  1450   var models = {
  1451     "Sony": [
  1452       {"name": "Bravia TV S1000", "type": "upnp", "service": "urn:schemas-upnp-org:service:RenderingControl:1" },
  1453       {"name": "Bravia TV S2000", "type": "zeroconf", "service": "_mediarenderer._http._tcp" },
  1454       {"name": "HiFi WD10", "type": "upnp", "service": "urn:schemas-upnp-org:service:RenderingControl:1" }
  1455     ],
  1456     "Philips": [ /* ... */ ],
  1457     "Alba": [ /* ... */ ]
  1458   };
  1459 
  1460   var makeEl = document.getElementById("make"),
  1461       modelEl = document.getElementById("model");
  1462 
  1463   makeEl.addEventListener('change', function() {
  1464     modelEl.innerHTML = ""; // reset
  1465     var defaultOption = document.createElement("option");
  1466     defaultOption.textContent = "Select model";
  1467     defaultOption.setAttribute("disabled", "disabled");
  1468     defaultOption.setAttribute("selected", "selected");
  1469     modelEl.appendChild(defaultOption);
  1470     for(var i = 0, l = models[makeEl.value].length; i < l; i++) {
  1471       var option = document.createElement("option");
  1472       option.textContent = models[makeEl.value][i]["name"];
  1473       option.setAttribute("value", models[makeEl.value][i]["type"] + ":" + models[makeEl.value][i]["service"]);
  1474       modelEl.appendChild(option);
  1475     }
  1476   }, false);
  1477 
  1478   modelEl.addEventListener('change', function() {
  1479     if(navigator.getNetworkServices &&
  1480          modelEl.value == "upnp:urn:schemas-upnp-org:service:RenderingControl:1") {
  1481       navigator.getNetworkServices(modelEl.value, successCallback, errorCallback);
  1482     } else if (modelEl.value == "zeroconf:_mediarenderer._http._tcp") {
  1483       debug.innerHTML += "&lt;br&gt;Service type is not implemented by this application.";
  1484     } else {
  1485       debug.innerHTML += "&lt;br&gt;Service Discovery is not supported!";
  1486     }
  1487   }, false);
  1488 &lt;/script&gt;
  1489 
  1490 &lt;script&gt;
  1491   function successCallback( services ) {
  1492 
  1493   // Listen for service push notification messages
  1494 
  1495     services[0].addEventListener('notify', function ( msg ) {
  1496          debug.innerHTML += "&lt;br>" + services[0].name + " event received: ";
  1497          debug.textContent += msg.data;
  1498     }, false);
  1499 
  1500  // Send a control signal to mute the service audio
  1501 
  1502     var svcXhr = new XMLHttpRequest();
  1503     svcXhr.open("POST", services[0].url); // services[0].url and its
  1504                                           // subresources have been whitelisted for
  1505                                           // cross-site XHR use in this current
  1506                                           // browsing context.
  1507 
  1508     svcXhr.setRequestHeader('SOAPAction', 'urn:schemas-upnp-org:service:RenderingControl:1#SetMute');
  1509     svcXhr.setRequestHeader('Content-Type', 'text/xml; charset="utf-8";');
  1510 
  1511     svcXhr.onreadystatechange = function ( response ) {
  1512       if( response.readyState != 4 || response.status != 200 )
  1513         return;
  1514       debug.innerHTML += "&lt;br&gt;" + services[0].name + " response received: ";
  1515       debug.textContent += response.responseXML;
  1516     }
  1517 
  1518     // Service messaging to mute the provided service
  1519     var svcMsg = '&lt;?xml version="1.0" encoding="utf-8"?&gt;' +
  1520                  '&lt;s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" ' +
  1521                    'xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"&gt;' +
  1522                    '&lt;s:Body&gt;' +
  1523                      '&lt;u:SetMute xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"&gt;' +
  1524                        '&lt;InstanceID&gt;0&lt;/InstanceID&gt;' +
  1525                        '&lt;Channel&gt;Master&lt;/Channel&gt;' +
  1526                        '&lt;DesiredMute&gt;true&lt;/DesiredMute&gt;' +
  1527                      '&lt;/u:SetMute&gt;' +
  1528                    '&lt;/s:Body&gt;' +
  1529                  '&lt;/s:Envelope&gt;';
  1530 
  1531     svcXhr.send(svcMsg);
  1532     debug.innerHTML += "&lt;br&gt;" + services[0].name + " request sent: ";
  1533     debug.textContent += svcMsg;
  1534   }
  1535 
  1536   function errorCallback( error ) {
  1537     debug.innerHTML += "&lt;br&gt;An error occurred: " + error.code;
  1538   }
  1539 &lt;/script&gt;</pre>
  1540           </div>
  1541 
  1542        </section>
  1543 
  1544     <section>
  1545       <h3>Acknowledgements</h3>
  1546 
  1547       <p>Thanks are expressed by the editor to the following individuals for their feedback on this specification to date (in alphabetical order):
  1548       <br /><br />
  1549       Gar Bergstedt, Lars-Erik Bolstad, Cathy Chan, Hari G Kumar, Bob Lund, Giuseppe Pascale, Marcin Simonides, Clarke Stevens, Christian S&ouml;derstr&ouml;m, Mark Vickers, ...</p>
  1550 
  1551       <p>Thanks are also expressed by the editor to the following organizations and groups for their support in producing this specification to date (in alphabetical order):
  1552       <br /></br />
  1553       CableLabs, Opera Software ASA, W3C Device APIs Working Group, W3C Web and TV Interest Group, ...</p>
  1554     </section>
  1555 </body>
  1556 </html>