discovery-api/Overview.src.html
author Rich Tibbett <richt@opera.com>
Mon, 12 Aug 2013 16:20:17 +1000
changeset 440 fcbaadc4fd54
parent 438 d66ca00fe7d9
child 441 b4b2569b4e9b
permissions -rw-r--r--
Fix [DAP-ISSUE-135]: Add security and privacy considerations section [Network Service Discovery]
richt@180
     1
<!DOCTYPE html>
richt@239
     2
<!--
richt@239
     3
richt@239
     4
  THIS IS THE WORKING VERSION OF THE CURRENT SPECIFICATION!
richt@239
     5
richt@239
     6
  This specification is built using ReSpec.js <http://dev.w3.org/2009/dap/ReSpec.js/documentation.html>
richt@239
     7
richt@239
     8
  From time to time it's necessary to HTML5 Tidy this document using the tool @ <http://w3c.github.com/tidy-html5/>.
richt@239
     9
richt@239
    10
  The command used to format this document (Overview.src.html) is as follows (replacing all = signs with - signs!):
richt@239
    11
richt@239
    12
  @> tidy ==new-blocklevel-tags section ==char-encoding utf8 ==tidy-mark no ==indent yes ==indent-spaces 2 ==indent-attributes yes ==wrap 120 ==fix-bad-comments yes -m Overview.src.html
richt@239
    13
richt@239
    14
  To publish a new compiled version (Overview.html), we need to open this file (Overview.src.html) in any web browser.
richt@239
    15
  Once it has loaded we press 'Ctrl + Shift + S' (or 'Cmd' + 'Shift' + 'S' on Mac) and then select
richt@239
    16
  'Save as HTML (Source)' from the resulting menu.
richt@239
    17
richt@239
    18
  We then replace Overview.html with the produced HTML source of this process.
richt@239
    19
richt@239
    20
  Next we run HTML5 Tidy over our new Overview.html file with the following command (replacing all = signs with - signs!):
richt@239
    21
richt@239
    22
  @> tidy ==new-blocklevel-tags section ==char-encoding utf8 ==tidy-mark no ==indent yes ==indent-spaces 2 ==indent-attributes yes ==wrap 120 ==hide-comments yes -m Overview.html
richt@239
    23
richt@239
    24
  Now the specification is ready to be published :)
richt@239
    25
richt@239
    26
-->
richt@180
    27
<html>
richt@180
    28
  <head>
richt@239
    29
    <title>
richt@239
    30
      Network Service Discovery
richt@239
    31
    </title>
richt@239
    32
    <meta http-equiv='Content-Type'
richt@239
    33
          content='text/html; charset=utf-8'>
richt@239
    34
    <script type="text/javascript"
richt@239
    35
          class='remove'>
richt@239
    36
var respecConfig = {
richt@191
    37
          specStatus:   "ED",
richt@402
    38
          //publishDate:  "2013-03-29",
richt@191
    39
          shortName:    "discovery-api",
richt@230
    40
          edDraftURI:   "http://dvcs.w3.org/hg/dap/raw-file/tip/discovery-api/Overview.html",
richt@241
    41
          previousMaturity: "FPWD",
richt@402
    42
          previousPublishDate: "2012-10-04",
richt@180
    43
          editors: [
richt@191
    44
            {
richt@191
    45
              name:       "Rich Tibbett",
richt@191
    46
              //url:        "http://richt.me/",
richt@191
    47
              company:    "Opera Software ASA",
richt@191
    48
              companyURL: "http://opera.com/"
richt@191
    49
            }
richt@180
    50
          ],
richt@398
    51
richt@241
    52
          wg:           "Device APIs Working Group",
richt@180
    53
          wgURI:        "http://www.w3.org/2009/dap/",
richt@180
    54
          wgPublicList: "public-device-apis",
richt@398
    55
          wgPatentURI:  "http://www.w3.org/2004/01/pp-impl/43696/status",
richt@398
    56
richt@437
    57
    //          extraCSS:     ["http://dvcs.w3.org/hg/dap/raw-file/tip/discovery-api/css/respec.nsd.css"],
richt@437
    58
    //          inlineCSS:    true,
richt@398
    59
          noIDLIn:      true
richt@398
    60
richt@180
    61
      };
richt@180
    62
    </script>
richt@239
    63
    <script src='http://www.w3.org/Tools/respec/respec-w3c-common'
richt@239
    64
          type="text/javascript"
richt@239
    65
          class='remove'
richt@437
    66
          async="">
richt@437
    67
</script>
richt@402
    68
    <style>
richt@437
    69
/* Custom ReSpec CSS (by Rich Tibbett) */
richt@402
    70
richt@402
    71
     /* Add better spacing to sections */
richt@402
    72
     section, .section { margin-bottom: 2em; }
richt@402
    73
richt@402
    74
     /* Reduce note & issue render size */
richt@402
    75
     .note, .issue { font-size:0.8em; }
richt@402
    76
richt@402
    77
     /* Add addition spacing to <ol> and <ul> for rule definition */
richt@402
    78
     ol.rule li, ul.rule li { padding:0.6em; }
richt@402
    79
richt@402
    80
     pre.widl { border: solid thin; background: #EEEEEE; color: black; padding: 0.5em 1em; position: relative; }
richt@402
    81
     pre.widl :link, pre.widl :visited { color: #000; background: transparent; }
richt@402
    82
     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 }
richt@402
    83
richt@402
    84
     div.example { border: solid thin black; background: #FFFFF0; color: black; padding: 0.5em 1em; position: relative; margin: 1em 0 1em 4.6em; width: auto; }
richt@402
    85
     div.example:before { content: "EXAMPLE"; font: bold small sans-serif; padding: 0.5em; background: white; color: black; position: absolute; top: 0; margin: -1px 0 0 -7.6em; width: 5em; border: thin solid black; border-radius: 0 0 0 0.5em }
richt@402
    86
richt@402
    87
     dl.domintro { color: green; margin: 2em 0 2em 2em; padding: 0.5em 1em; border: none; background: #DDFFDD; }
richt@402
    88
     hr + dl.domintro, div.impl + dl.domintro { margin-top: 2.5em; margin-bottom: 1.5em; }
richt@402
    89
     dl.domintro dt, dl.domintro dt * { color: black; text-decoration: none; }
richt@402
    90
     dl.domintro dd { margin: 0.5em 0 1em 2em; padding: 0; }
richt@402
    91
     dl.domintro dd p { margin: 0.5em 0; }
richt@402
    92
     dl.domintro code {font-size: inherit; font-style: italic; }
richt@402
    93
     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; font-size:0.8em; }
richt@402
    94
richt@402
    95
     table { border-collapse:collapse; border-style:hidden hidden none hidden }
richt@402
    96
     table thead { border-bottom:solid }
richt@402
    97
     table tbody th:first-child { border-left:solid }
richt@402
    98
     table td, table th { border-left:solid; border-right:solid; border-bottom:solid thin; vertical-align:top; padding:0.2em }
richt@437
    99
    </style>
richt@437
   100
    <script type="text/javascript"
richt@437
   101
          class="remove">
richt@437
   102
// RESPEC DEFINITIONS STYLE OVERLOAD
richt@437
   103
        window.addEventListener('load', function() {
richt@437
   104
          var overrideStyleEl = document.createElement('style');
richt@437
   105
          overrideStyleEl.textContent += "\n  a.externalDFN { color: #00C; border-bottom: 1px dashed #00C; }";
richt@437
   106
          overrideStyleEl.textContent += "\n  a.internalDFN { color: #00C; text-decoration: solid; }";
richt@437
   107
          document.querySelector('body').appendChild(overrideStyleEl);
richt@437
   108
        }, false);
richt@437
   109
    </script>
richt@180
   110
  </head>
richt@180
   111
  <body>
richt@180
   112
    <section id='abstract'>
richt@180
   113
      <p>
richt@239
   114
        This specification defines a mechanism for an HTML document to discover and subsequently communicate with
richt@239
   115
        <abbr title="Hypertext Transfer Protocol">HTTP</abbr>-based services advertised via common discovery protocols
richt@239
   116
        within the current network.
richt@180
   117
      </p>
richt@180
   118
    </section>
richt@180
   119
    <section id='sotd'>
richt@180
   120
      <p>
richt@239
   121
        This document represents the early consensus of the group on the scope and features of the proposed API.
richt@180
   122
      </p>
richt@180
   123
    </section>
richt@180
   124
    <section class="informative">
richt@239
   125
      <h3>
richt@239
   126
        Introduction
richt@239
   127
      </h3>
richt@180
   128
      <p>
richt@239
   129
        To enable Web pages to connect and communicate with Local-networked Services provided over HTTP, this
richt@239
   130
        specification introduces the <a href="#navigatornetworkservice"><code>NavigatorNetworkService</code></a>
richt@239
   131
        interface.
richt@180
   132
      </p>
richt@180
   133
      <p>
richt@239
   134
        Using this <abbr title="Application Programming Interface">API</abbr> consists of requesting a well-known
richt@239
   135
        service type, known by developers and advertised by Local-networked Devices. User authorization, where the user
richt@371
   136
        connects the web page to discovered services, is expected before the web page is able to interact with any
richt@371
   137
        Local-networked Services.
richt@180
   138
      </p>
richt@180
   139
      <p>
richt@239
   140
        A web page creates a request to obtain connectivity to services running in the network by specifying a
richt@239
   141
        well-known discovery service type that it wishes to interact with.
richt@180
   142
      </p>
richt@180
   143
      <p>
richt@250
   144
        The user agent, having captured all advertised services on the network from the <a>service discovery
richt@250
   145
        mechanisms</a> included in this recommendation, attempts to match the requested service type to a discovered
richt@250
   146
        service according to the processing described herein.
richt@180
   147
      </p>
richt@180
   148
      <p>
richt@437
   149
        If a service connectivity request is successful then the Web page is provided with a promise-based success
richt@437
   150
        callback with the all necessary information to communicate with the authorized Local-networked Service. If the
richt@437
   151
        request fails then the Web page will receive a promise-based error callback containing an error code describing
richt@437
   152
        the cause of Local-networked Service connectivity failure.
richt@180
   153
      </p>
richt@239
   154
      <p>
richt@239
   155
        Once connected to a Local-networked Service the Web page can send requests and receive responses to the
richt@239
   156
        Local-networked Service via the messaging format and appropriate channel inferred from the service type
richt@239
   157
        authorized via the provided API. The Web page, once connected, can also receive service-pushed events, in the
richt@239
   158
        messaging format supported by the Local-networked Device, if such event subscription functionality is provided
richt@239
   159
        by the connected Local-networked Service.
richt@239
   160
      </p>
richt@397
   161
      <p>
richt@437
   162
        Services available within the local network can connect and disconnect at different times during the execution
richt@437
   163
        of a web page. The user agent can inform a web page when the state of networked services matching any of the
richt@437
   164
        requested valid service types change. Web pages can use this information to enable in-page experiences for
richt@437
   165
        communicating the state of networked services with the ability to change the particular service or set of
richt@437
   166
        services the page is connected to (by re-invoking the <a href=
richt@397
   167
        "#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a> method defined herein).
richt@397
   168
      </p>
richt@180
   169
      <div class="example">
richt@239
   170
        <p>
richt@239
   171
          Example of requesting a DNS-SD advertised service:
richt@239
   172
        </p>
richt@239
   173
        <hr>
richt@239
   174
        <pre class="highlight">
richt@239
   175
function showServices( services ) {
richt@180
   176
  // Show a list of all the services provided to the web page
richt@239
   177
  for(var i = 0, l = services.length; i &lt; l; i++) console.log( services[i].name );
richt@180
   178
}
richt@180
   179
richt@437
   180
navigator.getNetworkServices('zeroconf:_boxee-jsonrpc._tcp').then(showServices);
richt@239
   181
</pre>
richt@180
   182
      </div>
richt@180
   183
      <div class="example">
richt@239
   184
        <p>
richt@239
   185
          Example of requesting a UPnP advertised service, also handling error conditions:
richt@239
   186
        </p>
richt@239
   187
        <hr>
richt@239
   188
        <pre class="highlight">
richt@239
   189
function showServices( services ) {
richt@180
   190
  // Show a list of all the services provided to the web page
richt@239
   191
  for(var i = 0, l = services.length; i &lt; l; i++) console.log( services[i].name );
richt@180
   192
}
richt@180
   193
richt@180
   194
function error( e ) {
richt@180
   195
  console.log( "Error occurred: " + e.code );
richt@180
   196
}
richt@180
   197
richt@437
   198
navigator.getNetworkServices('upnp:urn:schemas-upnp-org:service:ContentDirectory:1').then(showServices, error);
richt@239
   199
</pre>
richt@180
   200
      </div>
richt@180
   201
      <div class="example">
richt@239
   202
        <p>
richt@239
   203
          Example of requesting either a DNS-SD or UPnP advertised service:
richt@239
   204
        </p>
richt@239
   205
        <hr>
richt@239
   206
        <pre class="highlight">
richt@239
   207
function showServices( services ) {
richt@180
   208
  // Show a list of all the services provided to the web page (+ service type)
richt@239
   209
  for(var i = 0, l = services.length; i &lt; l; i++)
richt@180
   210
     console.log( services[i].name + '(' + services[i].type + ')' );
richt@180
   211
}
richt@180
   212
richt@180
   213
navigator.getNetworkServices([
richt@180
   214
  'zeroconf:_boxee-jsonrpc._tcp',
richt@180
   215
  'upnp:urn:schemas-upnp-org:service:ContentDirectory:1'
richt@437
   216
]).then(showServices);
richt@239
   217
</pre>
richt@180
   218
      </div>
richt@239
   219
      <p>
richt@440
   220
        For more detailed examples, including examples of communicating with obtained networked services, see the
richt@440
   221
        <a href="#examples">Examples</a> section.
richt@239
   222
      </p>
richt@180
   223
    </section>
richt@239
   224
    <section id='conformance'>
richt@239
   225
      <p>
richt@239
   226
        Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or
richt@239
   227
        "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should",
richt@239
   228
        "may", etc) used in introducing the algorithm.
richt@239
   229
      </p>
richt@239
   230
      <p>
richt@239
   231
        Some conformance requirements are phrased as requirements on attributes, methods or objects. Such requirements
richt@239
   232
        are to be interpreted as requirements on user agents.
richt@239
   233
      </p>
richt@239
   234
      <p>
richt@250
   235
        Conformance requirements phrased as algorithms or specific steps MAY be implemented in any manner, so long as
richt@250
   236
        the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be
richt@250
   237
        easy to follow, and not intended to be performant.)
richt@239
   238
      </p>
richt@239
   239
      <p>
richt@239
   240
        The only conformance class defined by this specification is a <dfn>user agent</dfn>.
richt@239
   241
      </p>
richt@239
   242
      <p>
richt@250
   243
        User agents MAY impose implementation-specific limits on otherwise unconstrained inputs, e.g. to prevent denial
richt@250
   244
        of service attacks, to guard against running out of memory, or to work around platform-specific limitations.
richt@239
   245
      </p>
richt@239
   246
      <p>
richt@239
   247
        When support for a feature is disabled (e.g. as an emergency measure to mitigate a security problem, or to aid
richt@250
   248
        in development, or for performance reasons), user agents MUST act as if they had no support for the feature
richt@250
   249
        whatsoever, and as if the feature was not mentioned in this specification. For example, if a particular feature
richt@250
   250
        is accessed via an attribute in a Web IDL interface, the attribute itself would be omitted from the objects
richt@250
   251
        that implement that interface - leaving the attribute on the object but making it return null or throw an
richt@250
   252
        exception is insufficient.
richt@239
   253
      </p>
richt@180
   254
      <section>
richt@239
   255
        <h3>
richt@239
   256
          Dependencies
richt@239
   257
        </h3>This specification relies on several other underlying specifications.
richt@239
   258
        <dl>
richt@239
   259
          <dt>
richt@239
   260
            HTML
richt@239
   261
          </dt>
richt@239
   262
          <dd>
richt@239
   263
            Many fundamental concepts from HTML are used by this specification. [[!HTML5]]
richt@239
   264
          </dd>
richt@239
   265
          <dt>
richt@239
   266
            WebIDL
richt@239
   267
          </dt>
richt@239
   268
          <dd>
richt@239
   269
            The IDL blocks in this specification use the semantics of the WebIDL specification. [[!WEBIDL]]
richt@239
   270
          </dd>
richt@239
   271
        </dl>
richt@180
   272
      </section>
richt@180
   273
    </section>
richt@180
   274
    <section>
richt@239
   275
      <h3>
richt@239
   276
        Terminology
richt@239
   277
      </h3>
richt@180
   278
      <p>
richt@239
   279
        The construction "a <code>Foo</code> object", where <code>Foo</code> is actually an interface, is sometimes
richt@239
   280
        used instead of the more accurate "an object implementing the interface <code>Foo</code>".
richt@180
   281
      </p>
richt@180
   282
      <p>
richt@239
   283
        The term DOM is used to refer to the API set made available to scripts in Web applications, and does not
richt@239
   284
        necessarily imply the existence of an actual <code>Document</code> object or of any other <code>Node</code>
richt@239
   285
        objects as defined in the DOM Core specifications. [[!DOM4]]
richt@180
   286
      </p>
richt@180
   287
      <p>
richt@239
   288
        An IDL attribute is said to be <em>getting</em> when its value is being retrieved (e.g. by author script), and
richt@239
   289
        is said to be <em>setting</em> when a new value is assigned to it.
richt@180
   290
      </p>
richt@180
   291
      <p>
danieldanciu@330
   292
        A <dfn>valid service type</dfn> is any of the following:
richt@180
   293
      </p>
richt@371
   294
      <ul>
richt@371
   295
        <li>a string that begins with <code>upnp:</code> or <code>zeroconf:</code> followed by one or more characters
richt@371
   296
        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,
richt@371
   297
        U+005E to U+007E.
richt@371
   298
        </li>
richt@371
   299
        <li>a string that begins with <code>dial:</code> followed by an integer version.
richt@371
   300
        </li>
richt@371
   301
      </ul>
richt@180
   302
      <p>
richt@239
   303
        A <a>valid service type</a> provided in the <code>type</code> attribute of the <a href=
richt@239
   304
        "#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a> method will be matched against the
richt@239
   305
        services currently contained in the <a>list of available service records</a> according to the algorithms
richt@239
   306
        defined in this specification.
richt@180
   307
      </p>
richt@230
   308
      <p>
richt@239
   309
        A <dfn>user-agent generated callback url</dfn> is a Local-network accessible URL endpoint that a <a>user
richt@239
   310
        agent</a> generates and maintains for receiving HTTP NOTIFY requests from UPnP Event sources. It is only
richt@239
   311
        required when the user agent implements UPnP Service Discovery as defined in this specification.
richt@230
   312
      </p>
richt@387
   313
      <p>
richt@387
   314
        In this specification we use the following terms to describe the processes required for Local-networked
richt@387
   315
        Services management:
richt@387
   316
      </p>
richt@387
   317
      <ul>
richt@387
   318
        <li>A <dfn>new service</dfn> is a Local-networked Service that has not previously been discovered or registered
richt@387
   319
        in the <a>list of available service records</a>.
richt@387
   320
        </li>
richt@387
   321
        <li>An <dfn>existing service</dfn> is a Local-networked Service that has previously been discovered and is
richt@387
   322
        registered in the <a>list of available service records</a>.
richt@387
   323
        </li>
richt@387
   324
        <li>A <dfn>current service</dfn> is a Local-networked Service, represented by a <a href=
richt@387
   325
        "#networkservice"><code>NetworkService</code></a> object, that is currently being shared with a web page via a
richt@387
   326
        <a href="#networkservices"><code>NetworkServices</code></a> object registered in the <a>list of active service
richt@387
   327
        managers</a>.
richt@387
   328
        </li>
richt@387
   329
      </ul>
richt@180
   330
    </section>
richt@180
   331
    <section>
richt@239
   332
      <h2>
richt@440
   333
        Security and privacy considerations
richt@440
   334
      </h2>
richt@440
   335
      <p>
richt@440
   336
        The API defined in this specification can be used to find and connect to devices and services within a user's
richt@440
   337
        current network. This discloses information related to a user's network: devices available on their network and
richt@440
   338
        the publicly-accessible services ("networked services") currently running and available on those devices. The
richt@440
   339
        distribution of this information could potentially compromise the user's privacy. A conforming implementation
richt@440
   340
        of this specification MUST provide a mechanism that protects the user's privacy. This mechanism MUST ensure
richt@440
   341
        that no networked service information is retrievable without the user's express permission.
richt@440
   342
      </p>
richt@440
   343
      <section>
richt@440
   344
        <h3>
richt@440
   345
          Privacy considerations for API implementations
richt@440
   346
        </h3>
richt@440
   347
        <p>
richt@440
   348
          A <a>user agent</a> MUST NOT provide networked service information to web sites without the express
richt@440
   349
          permission of the user. A user agent MUST acquire permission through a user interface, unless they have
richt@440
   350
          prearranged trust relationships with users, as described below. The user interface MUST include the document
richt@440
   351
          base URL. Those permissions that are acquired through the user interface and that are preserved beyond the
richt@440
   352
          current browsing session (i.e. beyond the time when the browsing context is navigated to another URL) MUST be
richt@440
   353
          revocable and a user agent MUST respect revoked permissions.
richt@440
   354
        </p>
richt@440
   355
        <p>
richt@440
   356
          Obtaining the user's express permission to access one API method does not imply the user has granted
richt@440
   357
          permission for the same web site to access any other methods that may be provided by this API, or to access
richt@440
   358
          the same method with a different set of arguments, as part of the same permission context. If a user has
richt@440
   359
          expressed permission for an implementation to, e.g. find a set of existing networked services, the
richt@440
   360
          implementation MUST seek the user's express permission if and when any subsequent functions are called on
richt@440
   361
          this API.
richt@440
   362
        </p>
richt@440
   363
        <p>
richt@440
   364
          A user agent MAY have prearranged trust relationships that do not require such user interfaces. For example,
richt@440
   365
          while a web browser will present a user interface when a web site performs a networked service lookup, a
richt@440
   366
          different runtime may have a prearranged, delegated security relationship with the user and, as such, a
richt@440
   367
          suitable alternative security and privacy mechanism with which to authorise the retrieval of networked
richt@440
   368
          service information.
richt@440
   369
        </p>
richt@440
   370
      </section>
richt@440
   371
      <section class="informative">
richt@440
   372
        <h3>
richt@440
   373
          Additional API implementation considerations
richt@440
   374
        </h3>
richt@440
   375
        <p>
richt@440
   376
          Further to the requirements listed in the previous section, implementors of the Network Service Discovery API
richt@440
   377
          are also advised to consider the following aspects that can negatively affect the privacy of their users: in
richt@440
   378
          certain cases, users can inadvertently grant permission to the user agent to disclose networked services to
richt@440
   379
          Web sites. In other cases, the content hosted at a certain URL changes in such a way that previously granted
richt@440
   380
          networked service permissions no longer apply as far as the user is concerned. Or the users might simply
richt@440
   381
          change their minds.
richt@440
   382
        </p>
richt@440
   383
        <p>
richt@440
   384
          Predicting or preventing these situations is inherently difficult. Mitigation and in-depth defensive measures
richt@440
   385
          are an implementation responsibility and not prescribed by this specification. However, in designing these
richt@440
   386
          measures, implementers are advised to enable user awareness of networked service sharing, and to provide easy
richt@440
   387
          access to interfaces that enable revocation of permissions that web applications have for accessing networked
richt@440
   388
          services via this API.
richt@440
   389
        </p>
richt@440
   390
      </section>
richt@440
   391
    </section>
richt@440
   392
    <section>
richt@440
   393
      <h2>
richt@239
   394
        Requesting networked services
richt@239
   395
      </h2>
richt@239
   396
      <pre class="widl">
richt@239
   397
[Supplemental, NoInterfaceObject]
richt@180
   398
interface <dfn id="navigatornetworkservice">NavigatorNetworkService</dfn> {
richt@437
   399
  <a class="externalDFN"
richt@437
   400
     href="http://dom.spec.whatwg.org/#promise">Promise</a> <a href=
richt@437
   401
     "#dom-navigator-getnetworkservices">getNetworkServices</a>( in any type );
richt@180
   402
};
richt@239
   403
<a class="externalDFN"
richt@239
   404
     href=
richt@239
   405
     "http://www.whatwg.org/specs/web-apps/current-work/complete/timers.html#navigator">Navigator</a> implements <a href=
richt@239
   406
     "#navigatornetworkservice">NavigatorNetworkService</a>;
richt@180
   407
richt@180
   408
[NoInterfaceObject]
richt@180
   409
interface <dfn id="navigatornetworkserviceerror">NavigatorNetworkServiceError</dfn> {
richt@180
   410
  const unsigned short <a href="#dom-navigatornetworkserviceerror-permission_denied">PERMISSION_DENIED_ERR</a> = 1;
richt@180
   411
  const unsigned short <a href="#dom-navigatornetworkserviceerror-unknown_type_prefix">UNKNOWN_TYPE_PREFIX_ERR</a> = 2;
richt@180
   412
  readonly attribute unsigned short <a href="#dom-navigatornetworkserviceerror-code">code</a>;
richt@180
   413
};
richt@180
   414
</pre>
richt@239
   415
      <section>
richt@239
   416
        <h2>
richt@239
   417
          Methods
richt@239
   418
        </h2>
richt@239
   419
        <dl class="domintro">
richt@239
   420
          <dt>
richt@437
   421
            <var title="">promise</var> = <var title="">window</var> . <code title="dom-navigator"><a href=
richt@239
   422
            "http://www.whatwg.org/specs/web-apps/current-work/complete/timers.html#navigator">navigator</a></code> .
richt@239
   423
            <code title="dom-navigator-getNetworkServices"><a href=
richt@437
   424
            "#dom-navigator-getnetworkservices">getNetworkServices</a></code> ( <var title="">type</var> )
richt@239
   425
          </dt>
richt@239
   426
          <dd>
richt@239
   427
            <p>
richt@437
   428
              Immediately returns a new <a href="http://dom.spec.whatwg.org/#promise"
richt@437
   429
                 class="externalDFN">Promise</a> object and then the user is prompted to select discovered network
richt@437
   430
                 services that have advertised support for the requested service type(s).
richt@239
   431
            </p>
richt@239
   432
            <p>
richt@239
   433
              The <var title="">type</var> argument contains one or more <a>valid service type</a> tokens that the web
richt@239
   434
              page would like to interact with.
richt@239
   435
            </p>
richt@239
   436
            <p>
richt@437
   437
              If the user accepts, the <var title="">promise</var> object is <a class="externalDFN"
richt@437
   438
                 href="http://dom.spec.whatwg.org/#concept-resolver-resolve">resolved</a>, with a <a href=
richt@437
   439
                 "#networkservices"><code>NetworkServices</code></a> object as its argument.
richt@239
   440
            </p>
richt@239
   441
            <p>
richt@437
   442
              If the user declines, or an error occurs, the <var title="">promise</var> object is <a class=
richt@437
   443
              "externalDFN"
richt@437
   444
                 href="http://dom.spec.whatwg.org/#concept-resolver-reject">rejected</a>.
richt@239
   445
            </p>
richt@239
   446
          </dd>
richt@239
   447
        </dl>
richt@239
   448
        <div>
richt@180
   449
          <p>
richt@239
   450
            When the <dfn id="dom-navigator-getnetworkservices"
richt@437
   451
               title="dom-navigator-getnetworkservices"><code>getNetworkServices(type)</code></dfn> method is called,
richt@437
   452
               the <a>user agent</a> MUST run the following steps:
richt@180
   453
          </p>
richt@180
   454
          <ol class="rule">
richt@437
   455
            <li>Let <var>Network Service Promise</var> be a new <a href="http://dom.spec.whatwg.org/#promise"
richt@437
   456
                  class="externalDFN"><code>Promise</code></a> object.
richt@437
   457
            </li>
richt@437
   458
            <li>Let <var>Network Service Promise's Resolver</var> be the default <a href=
richt@437
   459
            "http://dom.spec.whatwg.org/#concept-resolver"
richt@437
   460
                  class="externalDFN">resolver</a> of <var>Network Service Promise</var>.
richt@437
   461
            </li>
richt@437
   462
            <li>Return <var>Network Service Promise</var>, and run the remaining steps asynchronously.
richt@437
   463
            </li>
richt@239
   464
            <li>Let <var>requested control types</var> be initially set to an empty array.
richt@239
   465
            </li>
richt@239
   466
            <li>If <var>type</var> is an array consisting of one or more <a>valid service type</a> tokens, then let
richt@239
   467
            <var>requested control types</var> by the value of <var>type</var>, removing any non-<a>valid service
richt@239
   468
            type</a> tokens from the resulting array.
richt@239
   469
            </li>
richt@239
   470
            <li>If <var>type</var> is a string consisting of one <a>valid service type</a> token, then let
richt@239
   471
            <var>requested control types</var> be an array containing one item with a value of <var>type</var>.
richt@239
   472
            </li>
richt@239
   473
            <li>If <var>requested control types</var> is an array that contains at least one or more <a title=
richt@239
   474
            "valid service type">valid service type</a> tokens then continue to the step labeled <em>process</em>
richt@437
   475
            below. Otherwise, reject <var>Network Service Promise</var> by running the <a href=
richt@437
   476
            "http://dom.spec.whatwg.org/#concept-resolver-reject"
richt@437
   477
                  class="externalDFN">resolver reject algorithm</a> against the <var>Network Service Promise's
richt@437
   478
                  Resolver</var>, passing in a new <a href=
richt@239
   479
                  "#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object whose <a href=
richt@239
   480
                  "#dom-navigatornetworkserviceerror-code"><code>code</code></a> attribute has the numeric value 2
richt@239
   481
                  (<a href=
richt@239
   482
                  "#dom-navigatornetworkserviceerror-unknown_type_prefix"><code>UNKNOWN_TYPE_PREFIX_ERR</code></a>) as
richt@239
   483
                  its argument, abort any remaining steps and return.
richt@239
   484
            </li>
richt@180
   485
            <li>
richt@239
   486
              <em>Process</em>: Let <var>services found</var> be an empty array.
richt@180
   487
            </li>
richt@239
   488
            <li>For each <var>available service</var> in the <a>list of available service records</a> run the following
richt@239
   489
            steps:
richt@239
   490
              <ol class="rule">
richt@239
   491
                <li>For each <var>requested control type</var> in <var>requested control types</var>: If <var>available
richt@239
   492
                service</var>'s <code>type</code> attribute equals the <var>requested control type</var> then let <var>
richt@239
   493
                  matched service</var> equal the value of <var>available service</var> and continue at the step
richt@239
   494
                  labeled <var>attach</var> below.
richt@239
   495
                </li>
richt@239
   496
                <li>Continue at the next <var>available service</var>.
richt@239
   497
                </li>
richt@239
   498
                <li>
richt@239
   499
                  <em>Attach</em>: If <var>matched service</var> is not empty then run the following steps:
richt@239
   500
                  <ol class="rule">
richt@239
   501
                    <li>Let <var>new service object</var> be a new <a href=
richt@239
   502
                    "#networkservice"><code>NetworkService</code></a> object, mapping the parameters of <var>matched
richt@239
   503
                    service</var> to this new object where possible.
richt@239
   504
                    </li>
richt@239
   505
                    <li>Append <var>new service object</var> to the <var>services found</var> array.
richt@239
   506
                    </li>
richt@239
   507
                  </ol>
richt@239
   508
                </li>
richt@239
   509
              </ol>
richt@180
   510
            </li>
richt@239
   511
            <li>Optionally, e.g. based on a previously-established user preference, for security reasons, or due to
richt@437
   512
            platform limitations, the <a>user agent</a> MAY reject <var>Network Service Promise</var> by running the
richt@437
   513
            <a href="http://dom.spec.whatwg.org/#concept-resolver-reject"
richt@437
   514
                  class="externalDFN">resolver reject algorithm</a> against the <var>Network Service Promise's
richt@437
   515
                  Resolver</var>, passing in a new <a href=
richt@239
   516
                  "#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object whose <a href=
richt@239
   517
                  "#dom-navigatornetworkserviceerror-code"><code>code</code></a> attribute has the numeric value 1
richt@239
   518
                  (<a href=
richt@239
   519
                  "#dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></a>) as its
richt@239
   520
                  argument, abort any remaining steps and return.
richt@180
   521
            </li>
richt@371
   522
            <li>The user agent MUST NOT provide the entry script's origin with a <a href=
richt@371
   523
            "#networkservices"><code>NetworkServices</code></a> object without prior permission given by the user.
richt@239
   524
              <p>
richt@371
   525
                If <var>services found</var> is not an empty array then the <a>user agent</a> MAY choose to prompt the
richt@371
   526
                user in a user-agent-specific manner for permission to provide the <a href=
richt@371
   527
                "http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
richt@371
   528
                   class="externalDFN">entry script</a>'s <a href=
richt@371
   529
                   "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
richt@371
   530
                   class="externalDFN">origin</a> with a <a href="#networkservices"><code>NetworkServices</code></a>
richt@371
   531
                   object representing the <a>user-authorized</a> subset of <var>services found</var>.
richt@180
   532
              </p>
richt@239
   533
              <p>
richt@437
   534
                Alternatively, the user agent MAY wish to skip this user opt-in step and choose to fulfill <var>Network
richt@437
   535
                Service Promise</var> immediately based on a previously-established user preference, for security
richt@437
   536
                reasons, or due to platform limitations. In such an implementation, if <var>Network Service
richt@437
   537
                Promise</var> is to be fulfilled as a result of a previously-established user preference then the
richt@437
   538
                <a>user agent</a> MUST continue at the next step of this algorithm.
richt@371
   539
              </p>
richt@371
   540
              <p>
richt@371
   541
                If permission has been granted by the user to access one or more networked services then the <a>user
richt@371
   542
                agent</a> SHOULD include an "ongoing local-network communication" indicator.
richt@371
   543
              </p>
richt@371
   544
              <p>
richt@371
   545
                If permission has been denied by the user, <a>user agent</a> or platform, then the <a>user agent</a>
richt@437
   546
                MUST reject <var>Network Service Promise</var> by running the <a href=
richt@437
   547
                "http://dom.spec.whatwg.org/#concept-resolver-reject"
richt@437
   548
                   class="externalDFN">resolver reject algorithm</a> against the <var>Network Service Promise's
richt@437
   549
                   Resolver</var>, passing in a new <a href=
richt@239
   550
                   "#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object whose <a href=
richt@239
   551
                   "#dom-navigatornetworkserviceerror-code"><code>code</code></a> attribute has the numeric value 1
richt@239
   552
                   (<a href=
richt@239
   553
                   "#dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></a>) as its
richt@239
   554
                   argument, abort any remaining steps and return.
richt@239
   555
              </p>
richt@180
   556
              <p>
richt@371
   557
                If the user never responds or no previously-established user preference has been met, this algorithm
richt@371
   558
                stalls on this step.
richt@180
   559
              </p>
richt@180
   560
            </li>
richt@254
   561
            <li>Let <var>services</var> be an empty array.
richt@180
   562
            </li>
richt@371
   563
            <li>If <var>services found</var> is not an empty array then set <var>services</var> to be an array of one
richt@371
   564
            or more <a href="#networkservice"><code>NetworkService</code></a> objects for which the user granted
richt@371
   565
            permission above - known as the current objects <dfn>user-authorized</dfn> services.
richt@254
   566
            </li>
richt@377
   567
            <li>Remove all previously whitelisted urls from the <a>entry script origin's URL whitelist</a> granted in
richt@377
   568
            the current <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
richt@377
   569
                  class="externalDFN">entry script</a>'s <a href=
richt@377
   570
                  "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
richt@377
   571
                  class="externalDFN">origin</a>.
richt@377
   572
            </li>
richt@254
   573
            <li>For each Object <var>service</var> in <var>services</var>, if any, run the following sub-steps:
richt@239
   574
              <ol class="rule">
richt@239
   575
                <li>Add the <var>service</var>'s <code>url</code> parameter to the <a>entry script origin's
richt@239
   576
                  <abbr title="Uniform Resource Locator">URL</abbr> whitelist</a>.
richt@239
   577
                </li>
richt@239
   578
                <li>If <var>service</var>'s <code>type</code> parameter begins with the DOMString "<code>upnp:</code>"
richt@239
   579
                and the <var>service</var>'s <code>eventsUrl</code> parameter is not empty then <a>setup a UPnP Events
richt@239
   580
                Subscription</a> for <var>service</var>.
richt@239
   581
                </li>
richt@239
   582
              </ol>
richt@180
   583
            </li>
richt@239
   584
            <li>Let <var>services manager</var> be a new <a href="#networkservices"><code>NetworkServices</code></a>
richt@239
   585
            object.
richt@180
   586
            </li>
richt@375
   587
            <li>Store <var>requested control types</var> against <var>services manager</var> as an internal variable.
richt@375
   588
            </li>
richt@239
   589
            <li>Set <var>services manager</var>'s <a href=
richt@239
   590
            "#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute to the number of
richt@250
   591
            items currently found in the <a>list of available service records</a> whose <code>type</code> property
richt@239
   592
            matches any of the tokens requested in <var>requested control types</var>.
richt@180
   593
            </li>
richt@371
   594
            <li>Add <var>services</var>, if any, to the <var>services manager</var> object as its collection of
richt@371
   595
            <a>indexed properties</a>. If <var>services</var> is an empty array then the <var>services manager</var>
richt@371
   596
            does not have any <var>indexed properties</var>.
richt@250
   597
            </li>
richt@250
   598
            <li>Set <var>services manager</var>'s <a href="#dom-networkservices-length"><code>length</code></a>
richt@250
   599
            attribute to the number of items in <var>services</var>.
richt@250
   600
            </li>
richt@250
   601
            <li>Add <var>services manager</var> to the <a>list of active service managers</a>.
richt@180
   602
            </li>
richt@437
   603
            <li>The <a>user agent</a> MUST fulfill <var>Network Service Promise</var> by running the <a href=
richt@437
   604
            "http://dom.spec.whatwg.org/#concept-resolver-fulfill"
richt@437
   605
                  class="externalDFN">resolver fulfill algorithm</a> against the <var>Network Service Promise's
richt@437
   606
                  Resolver</var>, passing in <var>services manager</var> as its argument.
richt@180
   607
            </li>
richt@180
   608
          </ol>
richt@180
   609
          <p>
richt@239
   610
            The <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#task-source"
richt@239
   611
               class="externalDFN">task source</a> for these <a href=
richt@239
   612
               "http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#concept-task"
richt@239
   613
               class="externalDFN">tasks</a> is the <a href=
richt@239
   614
               "http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#user-interaction-task-source"
richt@239
   615
               class="externalDFN">user interaction task source</a>.
richt@180
   616
          </p>
richt@180
   617
          <p>
richt@239
   618
            When a <a href="#networkservice"><code>NetworkService</code></a> object is provided to a Web page, the
richt@250
   619
            <a>user agent</a> MUST add the <code>url</code> property to the <dfn>entry script origin's URL
richt@250
   620
            whitelist</dfn>. This list enables the Web page to override and initiate cross-site resource requests
richt@250
   621
            towards these URLs, and any sub-resources of these URLs, within the current <a href=
richt@239
   622
            "http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
richt@239
   623
               class="externalDFN">entry script</a>'s <a href=
richt@239
   624
               "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
richt@239
   625
               class="externalDFN">origin</a> via various existing mechanisms (e.g. Web Sockets, Server-Sent Events,
richt@239
   626
               Web Messaging, XMLHttpRequest).
richt@239
   627
          </p>
richt@180
   628
          <p>
richt@371
   629
            If the user navigates away from the <a href=
richt@371
   630
            "http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
richt@371
   631
               class="externalDFN">entry script</a>'s <a href=
richt@371
   632
               "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
richt@371
   633
               class="externalDFN">origin</a> then the <a>user agent</a> <em class="ct">MUST</em> remove all previously
richt@371
   634
               whitelisted urls from the <a>entry script origin's URL whitelist</a>. There is no persistence to network
richt@371
   635
               service selections provided to a web page. It is not possible to access a previously white-listed
richt@371
   636
               networked service without the necessary user authorization in all of the following cases:
richt@180
   637
          </p>
richt@239
   638
          <ul>
richt@239
   639
            <li>If the current script is reloaded at any point in the same or different window.
richt@239
   640
            </li>
richt@239
   641
            <li>if the current script reinvokes the <a href=
richt@239
   642
            "#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a> method at any point in its
richt@239
   643
            execution.
richt@239
   644
            </li>
richt@239
   645
            <li>If the user navigates forward or back in their history to reload the current page.
richt@239
   646
            </li>
richt@239
   647
            <li>If a script is running in a different origin.
richt@239
   648
            </li>
richt@239
   649
          </ul>
richt@239
   650
        </div>
richt@180
   651
      </section>
richt@180
   652
      <section>
richt@239
   653
        <h3>
richt@239
   654
          Error Handling
richt@239
   655
        </h3>
richt@239
   656
        <dl class="domintro">
richt@239
   657
          <dt>
richt@239
   658
            <var title="">error</var> . <code title="dom-NavigatorNetworkServiceError-code"><a href=
richt@239
   659
            "#dom-navigatornetworkserviceerror-code">code</a></code>
richt@239
   660
          </dt>
richt@239
   661
          <dd>
richt@239
   662
            <p>
richt@239
   663
              Returns the current error's error code. At the current time, this will be <code>1</code> or
richt@239
   664
              <code>2</code>, for which the corresponding error constants <a href=
richt@239
   665
              "#dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></a> and <a href=
richt@239
   666
              "#dom-navigatornetworkserviceerror-unknown_type_prefix"><code>UNKNOWN_TYPE_PREFIX_ERR</code></a> are
richt@239
   667
              defined.
richt@239
   668
            </p>
richt@239
   669
          </dd>
richt@239
   670
        </dl>
richt@239
   671
        <p>
richt@239
   672
          The <dfn id="dom-navigatornetworkserviceerror-code"
richt@239
   673
             title="dom-navigatornetworkserviceerror-code"><code>code</code></dfn> attribute of a <a href=
richt@239
   674
             "#navigatornetworkserviceerror"><code>NavigatorNetworkServiceError</code></a> object <em class=
richt@239
   675
             "ct">MUST</em> return the code for the error, which will be one of the following:
richt@239
   676
        </p>
richt@239
   677
        <dl>
richt@239
   678
          <dt>
richt@239
   679
            <dfn id="dom-navigatornetworkserviceerror-permission_denied"
richt@239
   680
                title="dom-navigatornetworkserviceerror-permission_denied"><code>PERMISSION_DENIED_ERR</code></dfn>
richt@239
   681
                (numeric value 1)
richt@239
   682
          </dt>
richt@239
   683
          <dd>
richt@239
   684
            The user or user agent denied the page permission to access any services.
richt@239
   685
          </dd>
richt@239
   686
          <dt>
richt@239
   687
            <dfn id="dom-navigatornetworkserviceerror-unknown_type_prefix"
richt@239
   688
                title="dom-navigatornetworkserviceerror-unknown_type_prefix"><code>UNKNOWN_TYPE_PREFIX_ERR</code></dfn>
richt@239
   689
                (numeric value 2)
richt@239
   690
          </dt>
richt@239
   691
          <dd>
richt@239
   692
            No <a>valid service type</a> tokens were provided in the method invocation.
richt@239
   693
          </dd>
richt@239
   694
        </dl>
richt@239
   695
      </section>
richt@239
   696
    </section>
richt@239
   697
    <section>
richt@239
   698
      <h2>
richt@239
   699
        Obtaining networked services
richt@239
   700
      </h2>
richt@180
   701
      <p>
richt@371
   702
        The <a href="#networkservices"><code>NetworkServices</code></a> interface represents a collection of zero or
richt@371
   703
        more <dfn>indexed properties</dfn> that are each a <a>user-authorized</a> <a href=
richt@371
   704
        "#networkservice"><code>NetworkService</code></a> object.
richt@254
   705
      </p>
richt@254
   706
      <p>
richt@437
   707
        A <a href="#networkservices"><code>NetworkServices</code></a> object is the <a href=
richt@437
   708
        "http://dom.spec.whatwg.org/#concept-promise-result"
richt@437
   709
           class="externalDFN">promise result</a> from a call to <a href=
richt@437
   710
           "#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a>.
richt@180
   711
      </p>
richt@239
   712
      <pre class="widl">
richt@180
   713
[NoInterfaceObject]
richt@180
   714
interface <dfn id="networkservices">NetworkServices</dfn> {
richt@180
   715
  readonly attribute unsigned long    <a href="#dom-networkservices-length">length</a>;
richt@180
   716
  getter <a href="#networkservice">NetworkService</a> (unsigned long index);
richt@239
   717
  <a href="#networkservice">NetworkService</a>? <a href=
richt@239
   718
"#dom-networkservices-getservicebyid">getServiceById</a>(DOMString id);
richt@180
   719
richt@180
   720
  readonly attribute unsigned long    <a href="#dom-networkservices-servicesavailable">servicesAvailable</a>;
richt@180
   721
richt@180
   722
  // event handler attributes
richt@239
   723
           attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler"
richt@239
   724
     class="externalDFN">EventHandler</a>     <a href="#dom-networkservices-onserviceavailable">onserviceavailable</a>;
richt@239
   725
           attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler"
richt@239
   726
     class="externalDFN">EventHandler</a>     <a href=
richt@239
   727
     "#dom-networkservices-onserviceunavailable">onserviceunavailable</a>;
richt@180
   728
richt@180
   729
};
richt@180
   730
richt@239
   731
<a href="#networkservices">NetworkServices</a> implements <a href=
richt@239
   732
"http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-eventtarget"
richt@239
   733
     class="externalDFN">EventTarget</a>;
richt@180
   734
</pre>
richt@180
   735
      <section>
richt@239
   736
        <h2>
richt@239
   737
          Attributes
richt@239
   738
        </h2>
richt@180
   739
        <dl class="domintro">
richt@180
   740
          <dt>
richt@239
   741
            <code title="dom-networkservices-length"><a href="#dom-networkservices-length">length</a></code>
richt@180
   742
          </dt>
richt@180
   743
          <dd>
richt@180
   744
            <p>
richt@398
   745
              Returns the current number of <a>indexed properties</a> in the current object's collection.
richt@180
   746
            </p>
richt@180
   747
          </dd>
richt@180
   748
          <dt>
richt@239
   749
            <code title="dom-networkservices-servicesavailable"><a href=
richt@239
   750
            "#dom-networkservices-servicesavailable">servicesAvailable</a></code>
richt@180
   751
          </dt>
richt@180
   752
          <dd>
richt@180
   753
            <p>
richt@250
   754
              Returns the current number of items matching one of the app-requested <a>valid service type</a> tokens in
richt@250
   755
              the <a>list of available service records</a>.
richt@180
   756
            </p>
richt@180
   757
          </dd>
richt@180
   758
        </dl>
richt@180
   759
        <div>
richt@239
   760
          <p>
richt@250
   761
            The <dfn id="dom-networkservices-length"><code>length</code></dfn> attribute MUST return the number of
richt@250
   762
            <a href="#networkservice"><code>NetworkService</code></a> objects represented by the collection.
richt@239
   763
          </p>
richt@239
   764
          <p>
richt@250
   765
            The <dfn id="dom-networkservices-servicesavailable"><code>servicesAvailable</code></dfn> attribute MUST
richt@250
   766
            return the number of services in the <a>list of available service records</a> whose <code>type</code>
richt@437
   767
            attribute matches any of the <a>valid service type</a> tokens that were initially used to create the
richt@437
   768
            current <a href="#networkservices"><code>NetworkServices</code></a> object.
richt@239
   769
          </p>
richt@180
   770
        </div>
richt@180
   771
      </section>
richt@180
   772
      <section>
richt@239
   773
        <h2>
richt@239
   774
          Methods
richt@239
   775
        </h2>
richt@180
   776
        <dl class="domintro">
richt@239
   777
          <dt>
richt@239
   778
            <code title="networkservices-getter"><a href="#networkservices">services</a></code> [ <var title=
richt@239
   779
            "">index</var> ]
richt@239
   780
          </dt>
richt@239
   781
          <dd>
richt@239
   782
            <p>
richt@239
   783
              Returns the specified <a href="#networkservice"><code>NetworkService</code></a> object.
richt@239
   784
            </p>
richt@239
   785
          </dd>
richt@239
   786
          <dt>
richt@239
   787
            <code title="networkservices-getter"><a href="#networkservices">services</a></code> . <code title=
richt@239
   788
            "dom-networkservices-getservicebyid"><a href=
richt@239
   789
            "#dom-networkservices-getservicebyid">getServiceById</a></code> ( <var title="">id</var> )
richt@239
   790
          </dt>
richt@239
   791
          <dd>
richt@239
   792
            <p>
richt@239
   793
              Returns the <a href="#networkservice"><code>NetworkService</code></a> object with the given identifier,
richt@239
   794
              or null if no service has that identifier.
richt@239
   795
            </p>
richt@239
   796
          </dd>
richt@239
   797
        </dl>
richt@239
   798
        <p>
richt@371
   799
          A <a href="#networkservices"><code>NetworkServices</code></a> object represents the current collection of
richt@371
   800
          zero or more <a href="#networkservice"><code>NetworkService</code></a> objects - its <a>indexed
richt@388
   801
          properties</a>. The <a>indexed properties</a> of a <a href=
richt@388
   802
          "#networkservices"><code>NetworkServices</code></a> object are <span>immutable</span> meaning that <a>indexed
richt@388
   803
          properties</a> cannot be added and <a>indexed properties</a> cannot be removed for the lifetime of a <a href=
richt@388
   804
          "#networkservices"><code>NetworkServices</code></a> object.
richt@239
   805
        </p>
richt@239
   806
        <p>
richt@239
   807
          The <a href=
richt@239
   808
          "http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#supported-property-indices"
richt@239
   809
             class="externalDFN">supported property indices</a> of <a href=
richt@239
   810
             "#networkservices"><code>NetworkServices</code></a> objects at any instant are the numbers from zero to
richt@250
   811
             the number of the <a href="#networkservice"><code>NetworkService</code></a> objects in the collection
richt@250
   812
             minus one.
richt@239
   813
        </p>
richt@398
   814
        <p class="note">
richt@398
   815
          Each service in a <a href="#networkservices"><code>NetworkServices</code></a> object thus has an index; the
richt@398
   816
          first has the index 0, and each subsequent service is numbered one higher than the previous one.
richt@398
   817
        </p>
richt@239
   818
        <p>
richt@239
   819
          To <a href=
richt@239
   820
          "http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#determine-the-value-of-an-indexed-property"
richt@239
   821
             class="externalDFN">determine the value of an indexed property</a> for a given index <var>index</var> in a
richt@250
   822
             <a href="#networkservices"><code>NetworkServices</code></a> object the user agent MUST return the <a href=
richt@250
   823
             "#networkservice"><code>NetworkService</code></a> object that represents the <var>index</var>th item in
richt@250
   824
             the collection.
richt@239
   825
        </p>
richt@239
   826
        <p>
richt@239
   827
          The <dfn id="dom-networkservices-getservicebyid"><code>getServiceById(id)</code></dfn> method <em class=
richt@239
   828
          "ct">MUST</em> return the first <a href="#networkservice"><code>NetworkService</code></a> object in the
richt@250
   829
          collection whose <a href="#dom-networkservice-id"><code>id</code></a> attribute is equal to the value of the
richt@250
   830
          <var>id</var> argument provided. When no <a href="#networkservice"><code>NetworkService</code></a> objects
richt@250
   831
          match the given argument, the method MUST return null.
richt@239
   832
        </p>
richt@180
   833
      </section>
richt@180
   834
      <section>
richt@239
   835
        <h2>
richt@239
   836
          Events
richt@239
   837
        </h2>
richt@239
   838
        <p>
richt@239
   839
          The following are the event handlers (and their corresponding event handler event types) that <em class=
richt@239
   840
          "ct">MUST</em> be supported, as IDL attributes, by all objects implementing the <a href=
richt@239
   841
          "#networkservices"><code>NetworkServices</code></a> interface:
richt@239
   842
        </p>
richt@243
   843
        <table border="1">
richt@239
   844
          <thead>
richt@239
   845
            <tr>
richt@239
   846
              <th>
richt@239
   847
                <span title="event handlers">Event handler</span>
richt@239
   848
              </th>
richt@239
   849
              <th>
richt@239
   850
                <span>Event handler event type</span>
richt@239
   851
              </th>
richt@239
   852
            </tr>
richt@239
   853
          </thead>
richt@239
   854
          <tbody>
richt@239
   855
            <tr>
richt@239
   856
              <td>
richt@239
   857
                <dfn id="dom-networkservices-onserviceavailable"
richt@239
   858
                    title="dom-NetworkServices-onserviceavailable"><code>onserviceavailable</code></dfn>
richt@239
   859
              </td>
richt@239
   860
              <td>
richt@239
   861
                <a href="#event-serviceavailable"><code>serviceavailable</code></a>
richt@239
   862
              </td>
richt@239
   863
            </tr>
richt@239
   864
            <tr>
richt@239
   865
              <td>
richt@239
   866
                <dfn id="dom-networkservices-onserviceunavailable"
richt@239
   867
                    title="dom-NetworkServices-onserviceunavailable"><code>onserviceunavailable</code></dfn>
richt@239
   868
              </td>
richt@239
   869
              <td>
richt@239
   870
                <a href="#event-serviceunavailable"><code>serviceunavailable</code></a>
richt@239
   871
              </td>
richt@239
   872
            </tr>
richt@239
   873
          </tbody>
richt@239
   874
        </table>
richt@180
   875
      </section>
richt@180
   876
    </section>
richt@180
   877
    <section>
richt@239
   878
      <h2>
richt@239
   879
        Communicating with a networked service
richt@239
   880
      </h2>
richt@239
   881
      <p>
richt@239
   882
        The <a href="#networkservice"><code>NetworkService</code></a> interface is used to provide a set of connection
richt@239
   883
        information for an HTTP service endpoint and if available, service events, running on a networked device.
richt@239
   884
      </p>
richt@239
   885
      <pre class="widl">
richt@180
   886
[NoInterfaceObject]
richt@180
   887
interface <dfn id="networkservice">NetworkService</dfn> {
richt@180
   888
  readonly attribute DOMString        <a href="#dom-networkservice-id">id</a>;
richt@180
   889
  readonly attribute DOMString        <a href="#dom-networkservice-name">name</a>;
richt@180
   890
  readonly attribute DOMString        <a href="#dom-networkservice-type">type</a>;
richt@180
   891
  readonly attribute DOMString        <a href="#dom-networkservice-url">url</a>;
richt@180
   892
  readonly attribute DOMString        <a href="#dom-networkservice-config">config</a>;
richt@180
   893
richt@191
   894
  readonly attribute boolean          <a href="#dom-networkservice-online">online</a>;
richt@180
   895
richt@180
   896
  // event handler attributes
richt@239
   897
           attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler"
richt@239
   898
     class="externalDFN">EventHandler</a>     <a href="#dom-networkservice-onserviceonline">onserviceonline</a>;
richt@239
   899
           attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler"
richt@239
   900
     class="externalDFN">EventHandler</a>     <a href="#dom-networkservice-onserviceoffline">onserviceoffline</a>;
richt@191
   901
richt@239
   902
           attribute <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#eventhandler"
richt@239
   903
     class="externalDFN">EventHandler</a>     <a href="#dom-networkservice-onnotify">onnotify</a>;
richt@180
   904
};
richt@180
   905
richt@239
   906
<a href="#networkservice">NetworkService</a> implements <a href=
richt@239
   907
"http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-eventtarget"
richt@239
   908
     class="externalDFN">EventTarget</a>;
richt@180
   909
</pre>
richt@239
   910
      <section>
richt@239
   911
        <h2>
richt@239
   912
          Attributes
richt@239
   913
        </h2>
richt@239
   914
        <dl class="domintro">
richt@239
   915
          <dt>
richt@239
   916
            <var title="">service</var> . <code title="dom-networkservice-id"><a href=
richt@239
   917
            "#dom-networkservice-id">id</a></code>
richt@239
   918
          </dt>
richt@239
   919
          <dd>
richt@239
   920
            <p>
richt@239
   921
              A unique identifier for the given user-selected service instance.
richt@239
   922
            </p>
richt@239
   923
          </dd>
richt@239
   924
          <dt>
richt@239
   925
            <var title="">service</var> . <code title="dom-networkservice-name"><a href=
richt@239
   926
            "#dom-networkservice-name">name</a></code>
richt@239
   927
          </dt>
richt@239
   928
          <dd>
richt@239
   929
            <p>
richt@239
   930
              The name of the user-selected service.
richt@239
   931
            </p>
richt@239
   932
          </dd>
richt@239
   933
          <dt>
richt@239
   934
            <var title="">service</var> . <code title="dom-networkservice-type"><a href=
richt@239
   935
            "#dom-networkservice-type">type</a></code>
richt@239
   936
          </dt>
richt@239
   937
          <dd>
richt@239
   938
            <p>
richt@239
   939
              The <a>valid service type</a> token value of the user-selected service.
richt@239
   940
            </p>
richt@239
   941
          </dd>
richt@239
   942
          <dt>
richt@239
   943
            <var title="">service</var> . <code title="dom-networkservice-url"><a href=
richt@239
   944
            "#dom-networkservice-url">url</a></code>
richt@239
   945
          </dt>
richt@239
   946
          <dd>
richt@239
   947
            <p>
richt@239
   948
              The control URL endpoint (including any required port information) of the user-selected control service
richt@239
   949
              that has been added to the <a>entry script origin's URL whitelist</a>.
richt@239
   950
            </p>
richt@239
   951
          </dd>
richt@239
   952
          <dt>
richt@239
   953
            <var title="">service</var> . <code title="dom-networkservice-config"><a href=
richt@239
   954
            "#dom-networkservice-config">config</a></code>
richt@239
   955
          </dt>
richt@239
   956
          <dd>
richt@239
   957
            <p>
richt@239
   958
              The configuration information associated with the service depending on the requested service type.
richt@239
   959
            </p>
richt@239
   960
          </dd>
richt@239
   961
        </dl>
richt@239
   962
        <p>
richt@239
   963
          The <dfn id="dom-networkservice-id"><code>id</code></dfn> attribute is a unique identifier for the service.
richt@250
   964
          The same service provided at different times or on different objects MUST have the same <a href=
richt@250
   965
          "#dom-networkservice-id"><code>id</code></a> value.
richt@239
   966
        </p>
richt@239
   967
        <p>
richt@239
   968
          The <dfn id="dom-networkservice-name"><code>name</code></dfn> attribute represents a human-readable title for
richt@239
   969
          the service.
richt@239
   970
        </p>
richt@239
   971
        <p>
richt@239
   972
          The <dfn id="dom-networkservice-type"><code>type</code></dfn> attribute reflects the value of the <a>valid
richt@239
   973
          service type</a> of the service.
richt@239
   974
        </p>
richt@239
   975
        <p>
richt@239
   976
          The <dfn id="dom-networkservice-url"><code>url</code></dfn> attribute is an <a href=
richt@239
   977
          "http://www.w3.org/TR/html5/urls.html#absolute-url"
richt@239
   978
             class="externalDFN">absolute URL</a> pointing to the root HTTP endpoint for the service that has been
richt@239
   979
             added to the <a>entry script origin's URL whitelist</a>. Web pages can subsequently use this value for
richt@239
   980
             implicit cross-document messaging via various existing mechanisms (e.g. Web Sockets, Server-Sent Events,
richt@239
   981
             Web Messaging, XMLHttpRequest).
richt@239
   982
        </p>
richt@239
   983
        <p>
richt@239
   984
          The <dfn id="dom-networkservice-config"><code>config</code></dfn> attribute provides the raw configuration
richt@239
   985
          information extracted from the given network service.
richt@239
   986
        </p>
richt@239
   987
      </section>
richt@239
   988
      <section>
richt@239
   989
        <h3>
richt@239
   990
          States
richt@239
   991
        </h3>
richt@239
   992
        <dl class="domintro">
richt@239
   993
          <dt>
richt@239
   994
            <var title="">service</var> . <code title="dom-networkservice-online"><a href=
richt@239
   995
            "#dom-networkservice-online">online</a></code>
richt@239
   996
          </dt>
richt@239
   997
          <dd>
richt@239
   998
            <p>
richt@239
   999
              Returns <code>true</code> if the service is reporting that it is accessible on the local network or
richt@390
  1000
              <code>false</code> if the service is no longer accessible (temporarily or permanently) on the local
richt@390
  1001
              network.
richt@239
  1002
            </p>
richt@239
  1003
          </dd>
richt@239
  1004
        </dl>
richt@239
  1005
        <p>
richt@239
  1006
          The <dfn id="dom-networkservice-online"><code>online</code></dfn> attribute indicates whether the service is
richt@390
  1007
          either <var>online</var>, and therefore accessible on the local network, in which case this attribute will
richt@390
  1008
          return <code>true</code> or, <var>offline</var>, and therefore not accessible on the local network, either
richt@390
  1009
          temporarily or permanently, in which case this attribute will return <code>false</code>. This attribute MUST
richt@390
  1010
          default to <code>true</code>.
richt@239
  1011
        </p>
richt@239
  1012
      </section>
richt@239
  1013
      <section>
richt@239
  1014
        <h3>
richt@239
  1015
          Events
richt@239
  1016
        </h3>
richt@239
  1017
        <p>
richt@239
  1018
          The following are the event handlers (and their corresponding event handler event types) that <em class=
richt@239
  1019
          "ct">MUST</em> be supported, as IDL attributes, by all objects implementing the <a href=
richt@239
  1020
          "#networkservice"><code>NetworkService</code></a> interface:
richt@239
  1021
        </p>
richt@243
  1022
        <table border="1">
richt@239
  1023
          <thead>
richt@239
  1024
            <tr>
richt@239
  1025
              <th>
richt@239
  1026
                <span title="event handlers">Event handler</span>
richt@239
  1027
              </th>
richt@239
  1028
              <th>
richt@239
  1029
                <span>Event handler event type</span>
richt@239
  1030
              </th>
richt@239
  1031
            </tr>
richt@239
  1032
          </thead>
richt@239
  1033
          <tbody>
richt@239
  1034
            <tr>
richt@239
  1035
              <td>
richt@239
  1036
                <dfn id="dom-networkservice-onnotify"
richt@239
  1037
                    title="dom-NetworkService-onnotify"><code>onnotify</code></dfn>
richt@239
  1038
              </td>
richt@239
  1039
              <td>
richt@239
  1040
                <a href="#event-notify"><code>notify</code></a>
richt@239
  1041
              </td>
richt@239
  1042
            </tr>
richt@239
  1043
            <tr>
richt@239
  1044
              <td>
richt@239
  1045
                <dfn id="dom-networkservice-onserviceonline"
richt@239
  1046
                    title="dom-NetworkService-onserviceonline"><code>onserviceonline</code></dfn>
richt@239
  1047
              </td>
richt@239
  1048
              <td>
richt@239
  1049
                <a href="#event-serviceonline"><code>serviceonline</code></a>
richt@239
  1050
              </td>
richt@239
  1051
            </tr>
richt@239
  1052
            <tr>
richt@239
  1053
              <td>
richt@239
  1054
                <dfn id="dom-networkservice-onserviceoffline"
richt@239
  1055
                    title="dom-NetworkService-onserviceoffline"><code>onserviceoffline</code></dfn>
richt@239
  1056
              </td>
richt@239
  1057
              <td>
richt@239
  1058
                <a href="#event-serviceoffline"><code>serviceoffline</code></a>
richt@239
  1059
              </td>
richt@239
  1060
            </tr>
richt@239
  1061
          </tbody>
richt@239
  1062
        </table>
richt@239
  1063
      </section>
richt@239
  1064
    </section>
richt@239
  1065
    <section>
richt@239
  1066
      <h2>
richt@239
  1067
        Service Discovery
richt@239
  1068
      </h2>
richt@239
  1069
      <p>
richt@243
  1070
        A <a>user agent</a> conforming to this specification MAY implement <abbr title=
richt@373
  1071
        "Simple Service Discovery Protocol">SSDP</abbr> [[!UPNP-DEVICEARCH11]], Zeroconf [[!DNS-SD]] + [[!MDNS]] and/or
richt@371
  1072
        <abbr title="Discovery and Launch Protocol">DIAL</abbr> [<a href=
richt@371
  1073
        "https://sites.google.com/a/dial-multiscreen.org/dial/dial-protocol-specification">DIAL</a>] <dfn>service
richt@371
  1074
        discovery mechanisms</dfn> - the requirements detailed in this section of the specification - to enable Web
richt@373
  1075
        pages to request and connect with HTTP services running on networked devices, discovered via any of these
richt@373
  1076
        mechanisms, through this API. When a <a>user agent</a> implements any of these <a>service discovery
richt@373
  1077
        mechanisms</a>, then it MUST conform to the corresponding algorithms provided in this section of the
richt@373
  1078
        specification.
richt@239
  1079
      </p>
richt@239
  1080
      <p>
richt@373
  1081
        This section presents how the results of these <a>service discovery mechanisms</a> will be matched to requested
richt@373
  1082
        service types, how the user agent stores available and active services and how their properties are applied to
richt@373
  1083
        any resulting <a href="#networkservice"><code>NetworkService</code></a> objects.
richt@239
  1084
      </p>
richt@239
  1085
      <p>
richt@250
  1086
        It is expected that user agents will perform these <a>service discovery mechanisms</a> asynchronously and
richt@250
  1087
        periodically update the <a>list of available service records</a> as required. The timing of any <a>service
richt@250
  1088
        discovery mechanisms</a> is an implementation detail left to the discretion of the implementer (e.g. by
richt@250
  1089
        continuously monitoring the network as a background process or on invocation of this API from a Web page).
richt@239
  1090
      </p>
richt@239
  1091
      <p>
richt@239
  1092
        The <dfn>list of available service records</dfn> is a single dynamic internal lookup table within user agents
richt@239
  1093
        that is used to track all the services that have been discovered and are available in the current network at
richt@440
  1094
        the current time. At any point during the running of any of the <a>service discovery mechanisms</a> then
richt@250
  1095
        existing entries within this table can be updated, entries can be added and entries can be removed as the
richt@250
  1096
        status of networked services changes according to the rules defined in this specification.
richt@239
  1097
      </p>
richt@239
  1098
      <p>
richt@250
  1099
        The <dfn>list of active service managers</dfn> is an internal list within user agents that is used to track all
richt@250
  1100
        <a href="#networkservices"><code>NetworkServices</code></a> objects currently being shared with any web pages
richt@371
  1101
        at the current time within the user agent. Each <a href="#networkservices"><code>NetworkServices</code></a>
richt@371
  1102
        object in the <a>list of active service managers</a> represents a collection of zero or more <a href=
richt@250
  1103
        "#networkservice"><code>NetworkService</code></a> objects - known as its <dfn>indexed properties</dfn>.
richt@250
  1104
        <a href="#networkservice"><code>NetworkService</code></a> objects are attached as the <a>indexed properties</a>
richt@250
  1105
        of a <a href="#networkservices"><code>NetworkServices</code></a> object as part of the <a href=
richt@239
  1106
        "#dom-navigator-getnetworkservices"><code>getNetworkServices()</code></a> algorithm.
richt@239
  1107
      </p>
richt@239
  1108
      <p>
richt@387
  1109
        The rule for <dfn>adding an available service</dfn> is the process of adding a <a>new service</a> or updating
richt@387
  1110
        an <a>existing service</a> that is generally available on the user's current network in the <a>list of
richt@387
  1111
        available service records</a>. This rule takes one argument, <var>network service record</var>, and consists of
richt@387
  1112
        running the following steps:
richt@239
  1113
      </p>
richt@239
  1114
      <ol class="rule">
richt@239
  1115
        <li>For each <var>existing service record</var> in the current <a>list of available service records</a>, run
richt@239
  1116
        the following sub-steps:
richt@239
  1117
          <ol class="rule">
richt@239
  1118
            <li>If the <var>existing service record</var>'s <code>id</code> property does not equal <var>network
richt@239
  1119
            service record</var>'s <code>id</code> property then abort any remaining sub-steps and continue at the next
richt@239
  1120
            available <var>existing service record</var>.
richt@239
  1121
            </li>
richt@239
  1122
            <li>Replace the value of <var>existing service record</var> in the current <a>list of available service
richt@373
  1123
            records</a> with the value of <var>network service record</var>, aborting any remaining steps in this
richt@373
  1124
            algorithm and return.
richt@239
  1125
            </li>
richt@239
  1126
          </ol>
richt@239
  1127
        </li>
richt@373
  1128
        <li>Add <var>network service record</var> to the <a>list of available service records</a> as a new item.
richt@239
  1129
        </li>
richt@250
  1130
        <li>For each <var>service manager</var> in the <a>list of active service managers</a> run the following steps:
richt@239
  1131
          <ol class="rule">
richt@250
  1132
            <li>For each <var>active service</var> in <var>service manager</var> run the following steps:
richt@250
  1133
              <ol class="rule">
richt@373
  1134
                <li>If the <var>network service record</var>'s <code>id</code> property equals the <var>active
richt@392
  1135
                service</var>'s <code>id</code> attribute and <var>active service</var>'s <code>online</code> attribute
richt@392
  1136
                is currently set to <code>false</code> then set <var>active service</var>'s <a href=
richt@250
  1137
                "#dom-networkservice-online"><code>online</code></a> attribute to <code>true</code> and then <a href=
richt@250
  1138
                "http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task"
richt@250
  1139
                      class="externalDFN">queue a task</a> to dispatch a newly created event with the name <a href=
richt@250
  1140
                      "#event-serviceonline"><code>serviceonline</code></a> that uses the <a href=
richt@250
  1141
                      "http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@250
  1142
                      class="externalDFN"><code>Event</code></a> interface, which does not bubble, is not cancellable,
richt@250
  1143
                      and has no default action, at the current <var>active service</var> object.
richt@250
  1144
                </li>
richt@250
  1145
              </ol>
richt@250
  1146
            </li>
richt@375
  1147
            <li>Let <var>'service type in current service manager' flag</var> be <code>false</code>.
richt@375
  1148
            </li>
richt@375
  1149
            <li>For each <var>requested control type</var> of the <var>requested control types</var> in <var>service
richt@375
  1150
            manager</var> run the following steps:
richt@375
  1151
              <ol class="rule">
richt@375
  1152
                <li>If <var>network service record</var>'s <code>type</code> property does not equal <var>requested
richt@375
  1153
                control type</var> then abort any remaining sub-steps and continue at the next available <var>requested
richt@375
  1154
                control type</var>.
richt@375
  1155
                </li>
richt@375
  1156
                <li>Set the <var>'service type in current service manager' flag</var> to <code>true</code>, abort any
richt@375
  1157
                remaining sub-steps and continue.
richt@375
  1158
                </li>
richt@375
  1159
              </ol>
richt@375
  1160
            </li>
richt@373
  1161
            <li>If the <var>'service type in current service manager' flag</var> is set to <code>true</code> then
richt@373
  1162
            increment <var>service manager</var>'s <a href=
richt@373
  1163
            "#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute by <code>1</code> and
richt@373
  1164
            then <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task"
richt@239
  1165
                  class="externalDFN">queue a task</a> to dispatch a newly created event with the name <a href=
richt@239
  1166
                  "#event-serviceavailable"><code>serviceavailable</code></a> that uses the <a href=
richt@239
  1167
                  "http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@239
  1168
                  class="externalDFN"><code>Event</code></a> interface, which does not bubble, is not cancellable, and
richt@250
  1169
                  has no default action, at the current <var>service manager</var> object.
richt@239
  1170
            </li>
richt@239
  1171
          </ol>
richt@239
  1172
        </li>
richt@239
  1173
      </ol>
richt@239
  1174
      <p>
richt@387
  1175
        The rule for <dfn>removing an available service</dfn> is the general process of removing an <a>existing
richt@387
  1176
        service</a> from the <a>list of available service records</a> that has left the user's current network or has
richt@387
  1177
        otherwise expired. This rule takes one argument, <var>service identifier</var>, and consists of running the
richt@387
  1178
        following steps:
richt@239
  1179
      </p>
richt@239
  1180
      <ol class="rule">
richt@239
  1181
        <li>For each <var>existing service record</var> in the current <a>list of available service records</a>, run
richt@239
  1182
        the following sub-steps:
richt@239
  1183
          <ol class="rule">
richt@239
  1184
            <li>If the <var>existing service record</var>'s <code>id</code> property does not match <var>service
richt@239
  1185
            identifier</var> then skip any remaining sub-steps for the current <var>existing service record</var> and
richt@239
  1186
            continue at the next available <var>existing service record</var>.
richt@239
  1187
            </li>
richt@378
  1188
            <li>Let <var>'service type in use' flag</var> be <code>false</code>.
richt@239
  1189
            </li>
richt@250
  1190
            <li>For each <var>service manager</var> in the <a>list of active service managers</a> run the following
richt@239
  1191
            steps:
richt@239
  1192
              <ol class="rule">
richt@373
  1193
                <li>Let <var>'service type in current service manager' flag</var> be <code>false</code>.
richt@239
  1194
                </li>
richt@250
  1195
                <li>For each <var>active service</var> in <var>service manager</var> run the following steps:
richt@250
  1196
                  <ol class="rule">
richt@250
  1197
                    <li>If <var>existing service record</var>'s <code>id</code> property equals the <var>active
richt@250
  1198
                    service</var>'s <code>id</code> attribute and <var>active service</var>'s <a href=
richt@250
  1199
                    "#dom-networkservice-online"><code>online</code></a> attribute is currently set to
richt@250
  1200
                    <code>true</code> then set <var>active service</var>'s <a href="#dom-networkservice-online"><code>
richt@250
  1201
                      online</code></a> attribute to <code>false</code> and then <a href=
richt@250
  1202
                      "http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task"
richt@250
  1203
                          class="externalDFN">queue a task</a> to dispatch a newly created event with the name <a href=
richt@250
  1204
                          "#event-serviceoffline"><code>serviceoffline</code></a> that uses the <a href=
richt@250
  1205
                          "http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@250
  1206
                          class="externalDFN"><code>Event</code></a> interface, which does not bubble, is not
richt@250
  1207
                          cancellable, and has no default action, at the current <var>active service</var>.
richt@250
  1208
                    </li>
richt@250
  1209
                  </ol>
richt@250
  1210
                </li>
richt@375
  1211
                <li>For each <var>requested control type</var> of the <var>requested control types</var> in
richt@375
  1212
                <var>service manager</var> run the following steps:
richt@375
  1213
                  <ol class="rule">
richt@375
  1214
                    <li>If <var>existing service record</var>'s <code>type</code> property does not equal
richt@375
  1215
                    <var>requested control type</var> then abort any remaining sub-steps and continue at the next
richt@375
  1216
                    available <var>requested control type</var>.
richt@375
  1217
                    </li>
richt@378
  1218
                    <li>Set the <var>'service type in current service manager' flag</var> to <code>true</code> and the
richt@378
  1219
                    <var>'service type in use' flag</var> to <code>true</code>, abort any remaining sub-steps and
richt@378
  1220
                    continue.
richt@375
  1221
                    </li>
richt@375
  1222
                  </ol>
richt@375
  1223
                </li>
richt@373
  1224
                <li>If the <var>'service type in current service manager' flag</var> is set to <code>true</code> then
richt@250
  1225
                decrement <var>service manager</var>'s <a href=
richt@250
  1226
                "#dom-networkservices-servicesavailable"><code>servicesAvailable</code></a> attribute by <code>1</code>
richt@250
  1227
                and then <a href=
richt@239
  1228
                "http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task"
richt@239
  1229
                      class="externalDFN">queue a task</a> to dispatch a newly created event with the name <a href=
richt@239
  1230
                      "#event-serviceunavailable"><code>serviceunavailable</code></a> that uses the <a href=
richt@239
  1231
                      "http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@239
  1232
                      class="externalDFN"><code>Event</code></a> interface, which does not bubble, is not cancellable,
richt@250
  1233
                      and has no default action, at the current <var>service manager</var> object.
richt@239
  1234
                </li>
richt@239
  1235
              </ol>
richt@239
  1236
            </li>
richt@378
  1237
            <li>If the <var>'service type in use' flag</var> is <code>false</code> and the <var>existing service
richt@378
  1238
            record</var>'s <code>type</code> property begins with the DOMString "<code>upnp:</code>" and <var>existing
richt@378
  1239
            service record</var>'s <code>eventsURL</code> property is set then run the rule to <a>terminate an existing
richt@378
  1240
            UPnP Events Subscription</a>, if one is currently active (as a result of having previously called <a>setup
richt@378
  1241
            a UPnP Events Subscription</a> against the current <var>existing service record</var>).
richt@378
  1242
            </li>
richt@239
  1243
            <li>Remove <var>existing service record</var> from the current <a>list of available service records</a>.
richt@239
  1244
            </li>
richt@239
  1245
          </ol>
richt@239
  1246
        </li>
richt@239
  1247
      </ol>
richt@239
  1248
      <p>
richt@250
  1249
        User agents SHOULD expire a service record from the <a>list of available service records</a> when its
richt@250
  1250
        <code>expiryTimestamp</code> attribute exceeds the current UTC timestamp. When this condition is met the
richt@250
  1251
        <a>user agent</a> SHOULD run the rule for <a>removing an available service</a>, passing in the expired service
richt@250
  1252
        record's <code>id</code> attribute as the only argument.
richt@239
  1253
      </p>
richt@239
  1254
      <section>
richt@239
  1255
        <h4>
richt@239
  1256
          Zeroconf (<abbr title="Multicast DNS">mDNS</abbr> + <abbr title="Domain Name System">DNS</abbr>-<abbr title=
richt@239
  1257
          "Service Discovery">SD</abbr>)
richt@239
  1258
        </h4>
richt@239
  1259
        <p>
richt@239
  1260
          For each DNS response received from a user-agent-initiated Multicast DNS Browse for <abbr title=
richt@239
  1261
          "DNS Pointer Record">PTR</abbr> records with the name <code>_services._dns-sd._udp</code> on the resolved
richt@250
  1262
          recommended automatic browsing domain [[!MDNS]], the <a>user agent</a> MUST run the following steps:
richt@239
  1263
        </p>
richt@239
  1264
        <ol class="rule">
richt@239
  1265
          <li>Let <var>service mDNS responses</var> be an array of PTR records received by issuing a Multicast DNS
richt@239
  1266
          Browse for PTR records with the name of the current discovered service type.
richt@239
  1267
          </li>
richt@239
  1268
          <li>For each Object <var>service mDNS response</var> in <var>service mDNS responses</var>, run the following
richt@239
  1269
          steps:
richt@239
  1270
            <ol>
richt@239
  1271
              <li>Let <var>network service record</var> be an Object consisting of the following empty properties:
richt@239
  1272
              <code>id</code>, <code>name</code>, <code>type</code>, <code>url</code>, <code>config</code>,
richt@239
  1273
              <code>expiryTimestamp</code>.
richt@239
  1274
              </li>
richt@239
  1275
              <li>Set <var>network service record</var>'s <code>id</code> property to the value of the full PTR Service
richt@239
  1276
              Instance Name [[!MDNS]].
richt@239
  1277
              </li>
richt@239
  1278
              <li>Set <var>network service record</var>'s <code>name</code> property to the value of the PTR Service
richt@239
  1279
              Instance Name's <var>Instance</var> component [[!MDNS]].
richt@239
  1280
              </li>
richt@239
  1281
              <li>Set <var>network service record</var>'s <code>type</code> property to the concatenation of the string
richt@239
  1282
              <code>zeroconf:</code> followed be the value of the PTR Service Instance Name's <var>Service</var>
richt@239
  1283
              component [[!MDNS]].
richt@239
  1284
              </li>
richt@239
  1285
              <li>Set <var>network service record</var>'s <code>url</code> property to the resolvable Service URL
richt@239
  1286
              obtained from performing an DNS-SD Lookup [[!DNS-SD]] of the current service from the PTR record provided
richt@239
  1287
              [[!MDNS]].
richt@239
  1288
              </li>
richt@239
  1289
              <li>Set <var>network service record</var>'s <code>config</code> property to the string value of the
richt@239
  1290
              contents of the first DNS-SD TXT record associated with the <var>service mDNS response</var> as defined
richt@239
  1291
              in [[!DNS-SD]].
richt@239
  1292
              </li>
richt@239
  1293
              <li>Set <var>network service record</var>'s <code>expiryTimestamp</code> property to the value of the
richt@239
  1294
              current date, in UTC timestamp format, plus a value of <code>120</code> seconds.
richt@239
  1295
              </li>
richt@239
  1296
              <li>Run the general rule for <a>adding an available service</a>, passing in the current <var>network
richt@239
  1297
              service record</var> as the only argument.
richt@239
  1298
              </li>
richt@239
  1299
            </ol>
richt@239
  1300
          </li>
richt@239
  1301
        </ol>
richt@239
  1302
      </section>
richt@239
  1303
      <section>
richt@239
  1304
        <h5>
richt@239
  1305
          Simple Service Discovery Protocol (<abbr title="Simple Service Discovery Protocol">SSDP</abbr>)
richt@239
  1306
        </h5>
richt@239
  1307
        <p>
richt@250
  1308
          A user agent that implements UPnP service discovery MUST issue a <dfn>search request for UPnP root
richt@250
  1309
          devices</dfn> against the user's current local network according to the full normative text and timing
richt@250
  1310
          provided in 'Section 1.3.2: Search request with M-SEARCH' detailed in [[!UPNP-DEVICEARCH11]].
richt@239
  1311
        </p>
richt@239
  1312
        <p>
richt@250
  1313
          The user agent MUST issue all <a title="search request for UPnP root devices">search requests for UPnP root
richt@250
  1314
          devices</a> with a HTTP request line equal to <code>M-SEARCH * HTTP/1.1</code>, with a HOST header equal to
richt@372
  1315
          the reserved multicast address and port of <code>239.255.255.250:1900</code> and a MAN header equal to
richt@372
  1316
          <code>ssdp:discover</code>. The <a>user agent</a> must also send an ST header with this HTTP request equal to
richt@372
  1317
          the String value of <code>ssdp:all</code> or <code>upnp:rootdevice</code> or a single <a>valid service
richt@391
  1318
          type</a> token beginning with the String value <code>upnp:</code>. If a single <a>valid service type</a>
richt@391
  1319
          token beginning with the String value <code>upnp:</code> is to be used, the user agent MUST strip the leading
richt@391
  1320
          String <code>upnp:</code> before using this value in this HTTP request. The user-agent MUST also send an MX
richt@391
  1321
          header equal to a <dfn>maximum UPnP advertisement response wait time</dfn> value between <code>1</code> and
richt@391
  1322
          <code>5</code> seconds with this HTTP request.
richt@239
  1323
        </p>
richt@239
  1324
        <p>
richt@250
  1325
          The user agent MUST listen for any incoming responses to any <a>search request for UPnP root devices</a>.
richt@239
  1326
        </p>
richt@239
  1327
        <p>
richt@250
  1328
          For each <dfn>HTTP Response</dfn> following an initial <a>search request for UPnP root devices</a> sent on a
richt@240
  1329
          <a>standard UPnP address and port</a> the user agent MUST run the following steps:
richt@239
  1330
        </p>
richt@239
  1331
        <ol class="rule">
richt@239
  1332
          <li>If the <a>HTTP Response</a> is not a HTTP 200 OK response then this response is invalid and the user
richt@250
  1333
          agent MUST discard this response, abort any remaining steps and return. The user agent MAY issue a new
richt@250
  1334
          <a>search request for UPnP root devices</a> as a result of this error occurring.
richt@250
  1335
          </li>
richt@250
  1336
          <li>If the <a>maximum UPnP advertisement response wait time</a> has been exceeded since the initial <a>search
richt@250
  1337
          request for UPnP root devices</a> was sent then the <a>HTTP Response</a> is invalid and the user agent MUST
richt@250
  1338
          discard this response, abort any remaining steps and return. The user agent MAY stop listening for responses
richt@250
  1339
          from the current <a>search request for UPnP root devices</a> as a result of this error occurring. Equally,
richt@250
  1340
          the user agent MAY issue a new <a>search request for UPnP root devices</a> as a result of this error
richt@239
  1341
          occurring.
richt@239
  1342
          </li>
richt@239
  1343
          <li>Let <var>ssdp device</var> be an Object with a property for each HTTP header received in the <a>HTTP
richt@239
  1344
          Response</a>, with each key being the name of a HTTP response header and each value being that HTTP response
richt@239
  1345
          header's value.
richt@239
  1346
          </li>
richt@239
  1347
          <li>If <var>ssdp device</var> does not contain at least one <var>CACHE-CONTROL</var> entry, at least one
richt@374
  1348
          <var>USN</var> entry, at least one <var>ST</var> entry and at least one <var>LOCATION</var> entry then the
richt@374
  1349
          <a>HTTP Response</a> is invalid and the <a>user agent</a> MUST discard this response, abort any remaining
richt@374
  1350
          steps and return.
richt@239
  1351
          </li>
richt@250
  1352
          <li>The user agent MUST run the rule for <a>obtaining a UPnP Device Description File</a> passing in the first
richt@250
  1353
          occurrence of <var>LOCATION</var> from <var>ssdp device</var> as the <var>device descriptor URL</var>
richt@250
  1354
          argument and the first occurrence of <var>USN</var> from <var>ssdp device</var> as the <var>device
richt@250
  1355
          identifier</var> argument and the first occurrence of <var>CACHE-CONTROL</var> from <var>ssdp device</var>
richt@250
  1356
          (minus the leading string of <code>max-age=</code>) as the <var>device expiry</var> argument.
richt@239
  1357
          </li>
richt@239
  1358
        </ol>
richt@239
  1359
        <p>
richt@250
  1360
          The user agent MUST listen for incoming requests on the <dfn>standard UPnP address and port</dfn> on all
richt@250
  1361
          current local network interface addresses with the port <code>1900</code>.
richt@250
  1362
        </p>
richt@250
  1363
        <p>
richt@250
  1364
          For each <dfn>HTTP Request</dfn> received on a <a>standard UPnP address and port</a> the user agent MUST run
richt@250
  1365
          the following steps:
richt@239
  1366
        </p>
richt@239
  1367
        <ol class="rule">
richt@239
  1368
          <li>If the <a>HTTP Request</a> is not a HTTP NOTIFY request then it is not a valid UPnP Request and the user
richt@250
  1369
          agent MUST discard this request, abort any remaining steps and return.
richt@239
  1370
          </li>
richt@239
  1371
          <li>Let <var>ssdp device</var> be an Object with a property for each HTTP header received in the <a>HTTP
richt@239
  1372
          Request</a>, with each key being the name of a HTTP header and each value being that HTTP header's value.
richt@239
  1373
          </li>
richt@374
  1374
          <li>If <var>ssdp device</var>'s <var>NTS</var> entry is equal to <code>ssdp:alive</code> and the <a>HTTP
richt@374
  1375
          Request</a> does not contain at least one <var>CACHE-CONTROL</var> entry, at least one <var>USN</var> entry,
richt@374
  1376
          at least one <var>NT</var> entry, at least one <var>NTS</var> entry and at least one <var>LOCATION</var>
richt@374
  1377
          entry, then the <a>user agent</a> MUST discard this request, abort any remaining steps and return.
richt@239
  1378
          </li>
richt@250
  1379
          <li>If <var>ssdp device</var>'s <var>NTS</var> entry is equal to <code>ssdp:alive</code> then the user agent
richt@250
  1380
          MUST run the rule for <a>obtaining a UPnP Device Description File</a> passing in the first occurrence of
richt@250
  1381
          <var>LOCATION</var> from <var>ssdp device</var> as the <var>device descriptor URL</var> argument and the
richt@250
  1382
          first occurrence of <var>USN</var> from <var>ssdp device</var> as the <var>device identifier</var> argument
richt@250
  1383
          and the first occurrence of <var>CACHE-CONTROL</var> from <var>ssdp device</var> (minus the leading string of
richt@250
  1384
          <code>max-age=</code>) as the <var>device expiry</var>.<br>
richt@239
  1385
            <br>
richt@239
  1386
            Otherwise, if <var>ssdp device</var>'s <var>NTS</var> entry is equal to <code>ssdp:byebye</code> then the
richt@250
  1387
            user agent MUST run the rule for <a>removing all services from a registered UPnP Device</a> passing in the
richt@250
  1388
            first occurrence of <var>USN</var> from <var>ssdp device</var> as the <var>device identifier</var>
richt@250
  1389
            argument.
richt@239
  1390
          </li>
richt@239
  1391
        </ol>
richt@239
  1392
        <p>
richt@239
  1393
          The rule for <dfn>obtaining a UPnP Device Description File</dfn> is the process of obtaining the contents of
richt@239
  1394
          a standard UPnP Device Description [[!UPNP-DEVICEARCH11]] from a URL-based resource. This rule takes three
richt@239
  1395
          arguments - <var>device descriptor URL</var>, <var>device identifier</var> and <var>device expiry</var> - and
richt@240
  1396
          when called the user agent MUST run the following steps:
richt@239
  1397
        </p>
richt@239
  1398
        <ol class="rule">
richt@239
  1399
          <li>Let <var>device descriptor file</var> contain the contents of the file located at the URL provided in
richt@239
  1400
          <var>device descriptor URL</var> obtained according to the rules defined in 'Section 2.11: Retrieving a
richt@239
  1401
          description using HTTP' in [[!UPNP-DEVICEARCH11]].
richt@239
  1402
          </li>
richt@239
  1403
          <li>If the value provided in <var>device descriptor URL</var> cannot be resolved as a reachable URL on the
richt@250
  1404
          current network or the <var>device descriptor file</var> remains empty then it is invalid and the <a>user
richt@250
  1405
          agent</a> MUST abort any remaining steps and return.
richt@239
  1406
          </li>
richt@239
  1407
          <li>Run the rule for <a>processing a UPnP Device Description File</a>, passing in the current <var>device
richt@239
  1408
          descriptor file</var>, <var>device identifier</var> and <var>device expiry</var> arguments.
richt@239
  1409
          </li>
richt@239
  1410
        </ol>
richt@239
  1411
        <p>
richt@239
  1412
          The rule for <dfn>processing a UPnP Device Description File</dfn> is the process of parsing the contents of a
richt@239
  1413
          standard UPnP Device Description [[!UPNP-DEVICEARCH11]] and registering the UPnP services contained therein
richt@239
  1414
          within the <a>list of available service records</a>.
richt@239
  1415
        </p>
richt@239
  1416
        <p>
richt@239
  1417
          The rule for <a>processing a UPnP Device Description File</a> takes three arguments - <var>device descriptor
richt@250
  1418
          file</var>, <var>device identifier</var> and <var>device expiry</var> - and when called the user agent MUST
richt@250
  1419
          run the following steps:
richt@239
  1420
        </p>
richt@239
  1421
        <ol class="rule">
richt@239
  1422
          <li>Let <var>advertised services</var> be a list of all advertised services obtained from the <var>device
richt@239
  1423
          descriptor file</var> containing the value of the first occurrence of the <code>&lt;serviceList&gt;</code>
richt@239
  1424
          element as it is defined in 'Section 2.3: Device Description' in [[!UPNP-DEVICEARCH11]].
richt@239
  1425
          </li>
richt@239
  1426
          <li>For each <code>&lt;service&gt;</code> element - known as an <var>advertised service</var> - in
richt@239
  1427
          <var>advertised services</var> run the following steps:
richt@239
  1428
            <ol class="rule">
richt@239
  1429
              <li>Let <var>network service record</var> be a new Object consisting of the following empty properties:
richt@239
  1430
              <code>id</code>, <code>deviceId</code>, <code>name</code>, <code>type</code>, <code>url</code>,
richt@239
  1431
              <code>eventsUrl</code>, <code>config</code>, <code>expiryTimestamp</code>.
richt@239
  1432
              </li>
richt@239
  1433
              <li>Set <var>network service record</var>'s <code>id</code> property to the concatenated string value of
richt@250
  1434
              the first occurrence of the <code>&lt;UDN&gt;</code> element in the <var>device descriptor file</var>
richt@250
  1435
              with the <var>advertised service</var>'s <code>&lt;serviceId&gt;</code> sub-element.
richt@239
  1436
              </li>
richt@239
  1437
              <li>Set <var>network service record</var>'s <code>deviceId</code> property to the value of <var>device
richt@239
  1438
              identifier</var>.
richt@239
  1439
              </li>
richt@239
  1440
              <li>Set <var>network service record</var>'s <code>name</code> property to the string value of the first
richt@239
  1441
              occurrence of the <var>advertised service</var>'s <code>&lt;serviceId&gt;</code> sub-element.
richt@239
  1442
              </li>
richt@239
  1443
              <li>Set <var>network service record</var>'s <code>type</code> property to the concatenation of the string
richt@239
  1444
              <code>upnp:</code> followed by the string value of the first occurrence of the <var>advertised
richt@239
  1445
              service</var>'s <code>&lt;serviceType&gt;</code> sub-element.
richt@239
  1446
              </li>
richt@239
  1447
              <li>Set <var>network service record</var>'s <code>url</code> property to the string value of the first
richt@239
  1448
              occurrence of the <var>advertised service</var>'s <code>&lt;controlURL&gt;</code> sub-element.
richt@239
  1449
              </li>
richt@239
  1450
              <li>Set <var>network service record</var>'s <code>config</code> property to the string value of the
richt@239
  1451
              contents of the first occurrence of the <code>&lt;device&gt;</code> element in the <var>device descriptor
richt@239
  1452
              file</var>.
richt@239
  1453
              </li>
richt@239
  1454
              <li>If <var>advertised service</var>'s <code>&lt;eventSubURL&gt;</code> sub-element is not empty, then
richt@239
  1455
              set <var>network service record</var>'s <code>eventsUrl</code> property to the string value of the first
richt@239
  1456
              occurrence of the <var>advertised service</var>'s <code>&lt;eventSubURL&gt;</code> sub-element.
richt@239
  1457
              Otherwise, do not set <var>network service record</var>'s <code>eventsUrl</code> property.
richt@239
  1458
              </li>
richt@239
  1459
              <li>Set <var>network service record</var>'s <code>expiryTimestamp</code> property to the value of the
richt@239
  1460
              current date, in UTC timestamp format, plus the value of <var>device expiry</var>.
richt@239
  1461
              </li>
richt@239
  1462
              <li>Run the general rule for <a>adding an available service</a>, passing in the current <var>network
richt@239
  1463
              service record</var> as the only argument.
richt@239
  1464
              </li>
richt@239
  1465
            </ol>
richt@239
  1466
          </li>
richt@250
  1467
          <li>If <var>device descriptor file</var> contains a <code>&lt;deviceList&gt;</code> element then for each
richt@250
  1468
          <code>&lt;device&gt;</code> element within <code>&lt;deviceList&gt;</code> - herein known as an <var>embedded
richt@250
  1469
          device descriptor file</var> - the user agent MUST run the rule for <a>processing a UPnP Device Description
richt@250
  1470
          File</a>, passing in the current <var>embedded device descriptor file</var> as the <var>device descriptor
richt@250
  1471
          file</var> argument, along with the current <var>device identifier</var> and <var>device expiry</var>
richt@250
  1472
          arguments.
richt@250
  1473
          </li>
richt@239
  1474
        </ol>
richt@239
  1475
        <p>
richt@239
  1476
          The rule for <dfn>removing all services from a registered UPnP Device</dfn> is the process of removing all
richt@239
  1477
          services associated with a device from the <a>list of available service records</a> that has left the user's
richt@239
  1478
          current network or has otherwise timed out or expired. This rule takes one argument, <var>device
richt@239
  1479
          identifier</var>, and consists of running the following steps:
richt@239
  1480
        </p>
richt@239
  1481
        <ol class="rule">
richt@239
  1482
          <li>For each <var>existing service record</var> in the current <a>list of available service records</a>, run
richt@239
  1483
          the following sub-steps:
richt@239
  1484
            <ol class="rule">
richt@239
  1485
              <li>If the <var>existing service record</var>'s <code>deviceId</code> property does not match <var>device
richt@239
  1486
              identifier</var> then skip any remaining sub-steps for the current <var>existing service record</var> and
richt@239
  1487
              continue at the next available <var>existing service record</var>.
richt@239
  1488
              </li>
richt@239
  1489
              <li>Run the general rule for <a>removing an available service</a> passing in <var>existing service
richt@239
  1490
              record</var>'s <code>id</code> property as the only argument.
richt@239
  1491
              </li>
richt@239
  1492
            </ol>
richt@239
  1493
          </li>
richt@239
  1494
        </ol>
richt@239
  1495
        <p>
richt@239
  1496
          When the <a>user agent</a> is to <dfn>setup a UPnP Events Subscription</dfn>, it is to run the following
richt@239
  1497
          steps with the current <var>network service record</var> object as defined in 'Section 4.1.2: SUBSCRIBE with
richt@239
  1498
          NT and CALLBACK' in [[!UPNP-DEVICEARCH11]]:
richt@239
  1499
        </p>
richt@239
  1500
        <ol class="rule">
richt@239
  1501
          <li>If <var>network service record</var>'s <code>eventsUrl</code> property is empty then the <a>user
richt@240
  1502
          agent</a> MUST abort these steps.
richt@239
  1503
          </li>
richt@239
  1504
          <li>Let <var>callback URL</var> be the value of creating a new <a>user-agent generated callback url</a>.
richt@239
  1505
          </li>
richt@239
  1506
          <li>Send a HTTP SUBSCRIBE request with a <em>NT</em> header with a string value of <code>upnp:event</code>, a
richt@239
  1507
          <em>TIMEOUT</em> header with a user-agent defined timeout value (in the form <code>Second-XX</code> where
richt@239
  1508
          <code>XX</code> is the user-agent defined timeout value in seconds) and a <em>CALLBACK</em> header with a
richt@239
  1509
          string value of <var>callback URL</var> towards the <var>network service record</var>'s
richt@239
  1510
          <code>eventsUrl</code> property.
richt@239
  1511
          </li>
richt@250
  1512
          <li>If a non-200 OK response is received from the HTTP SUBSCRIBE request then the <a>user agent</a> MUST
richt@250
  1513
          abort these steps.
richt@239
  1514
          </li>
richt@239
  1515
          <li>On receiving a valid 200 OK response, run the following steps:
richt@239
  1516
            <ol class="rule">
richt@239
  1517
              <li>Let <var>callback ID</var> equal the string value of the first included <em>SID</em> header, if it
richt@239
  1518
              exists.
richt@239
  1519
              </li>
richt@239
  1520
              <li>Let <var>timeout date</var> equal the sum of the current UTC date value plus the integer value of the
richt@239
  1521
              first included <em>TIMEOUT</em> header (minus the leading string of <code>Second-</code>), if it exists.
richt@239
  1522
              </li>
richt@240
  1523
              <li>Run the following steps asynchronously and continue to the step labeled <em>listen</em> below.
richt@239
  1524
              </li>
richt@239
  1525
              <li>
richt@239
  1526
                <em>Refresh Subscription</em>: Run the following steps at a set interval (X) within the <a>user
richt@239
  1527
                agent</a>:
richt@239
  1528
                <ol class="rule">
richt@239
  1529
                  <li>Let <var>current date</var> equal the current UTC date.
richt@239
  1530
                  </li>
richt@239
  1531
                  <li>If <var>current date</var> is less than the <var>timeout date</var> then continue to the step
richt@239
  1532
                  labeled <em>refresh subscription</em> above.
richt@239
  1533
                  </li>
richt@239
  1534
                  <li>Send a HTTP SUBSCRIBE request with a <em>SID</em> header with the string value of <var>callback
richt@239
  1535
                  ID</var> and a user-agent defined <em>TIMEOUT</em> header (in the form <code>Second-XX</code> where
richt@239
  1536
                  <code>XX</code> is the user-agent defined timeout value in seconds) towards the <var>network service
richt@239
  1537
                  record</var>'s <code>eventsUrl</code> property.
richt@239
  1538
                  </li>
richt@239
  1539
                  <li>On receiving a valid 200 OK, update <var>callback ID</var> with the string value of the first
richt@250
  1540
                  included <em>SID</em> header and set <var>timeout date</var> to the sum of the current UTC date value
richt@250
  1541
                  plus the integer value of the first included <em>TIMEOUT</em> header (minus the leading string of
richt@250
  1542
                  <code>Second-</code>), if it exists. If the current date is greater than or equal to <var>timeout
richt@250
  1543
                  date</var> then the <a>user agent</a> SHOULD continue from the step labeled <em>refresh
richt@250
  1544
                  subscription</em> above. For all non 200 OK responses the <a>user agent</a> SHOULD continue from the
richt@250
  1545
                  step labeled <em>refresh subscription</em> above.
richt@239
  1546
                  </li>
richt@239
  1547
                </ol>
richt@239
  1548
              </li>
richt@239
  1549
              <li>
richt@239
  1550
                <em>Listen</em>: For each HTTP NOTIFY request received at the <var>callback URL</var> the <a>user
richt@239
  1551
                agent</a> is to run the following steps:
richt@239
  1552
                <ol class="rule">
richt@239
  1553
                  <li>Let <var>content clone</var> be the result of obtaining the message body of the HTTP NOTIFY
richt@250
  1554
                  request. If <var>content clone</var> is empty, then the <a>user agent</a> MUST abort these steps.
richt@239
  1555
                  </li>
richt@239
  1556
                  <li>Let <var>notification event</var> be a new simple event that uses the <a href=
richt@239
  1557
                  "http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@239
  1558
                        class="externalDFN"><code>Event</code></a> interface with the name <a href=
richt@239
  1559
                        "#event-notify"><code>notify</code></a>, which does not bubble, is not cancellable, and has no
richt@239
  1560
                        default action.
richt@239
  1561
                  </li>
richt@239
  1562
                  <li>Let the <code>data</code> attribute of <var>notification event</var> have the DOMString value of
richt@239
  1563
                  <var>content clone</var>.
richt@239
  1564
                  </li>
richt@239
  1565
                  <li>
richt@239
  1566
                    <a href="http://www.whatwg.org/specs/web-apps/current-work/complete/webappapis.html#queue-a-task"
richt@239
  1567
                        class="externalDFN">Queue a task</a> to dispatch <var>notification event</var> at the current
richt@239
  1568
                        <a><code>NetworkService</code></a> object.
richt@239
  1569
                  </li>
richt@250
  1570
                  <li>Return a HTTP 200 OK response to the sender of the HTTP NOTIFY request.
richt@250
  1571
                  </li>
richt@239
  1572
                </ol>
richt@239
  1573
              </li>
richt@239
  1574
            </ol>
richt@239
  1575
          </li>
richt@239
  1576
        </ol>
richt@239
  1577
        <p>
richt@250
  1578
          A <a>user agent</a> can <dfn>terminate an existing UPnP Events Subscription</dfn> at any time for a
richt@250
  1579
          <var>network service record</var> by sending an HTTP UNSUBSCRIBE request - as defined in 'Section 4.1.4:
richt@250
  1580
          Cancelling a subscription with UNSUBSCRIBE' in [[!UPNP-DEVICEARCH11]] - with a HOST header set to that
richt@250
  1581
          <var>active service</var>'s <code>eventsUrl</code> property and a SID header set to the <var>callback
richt@250
  1582
          ID</var> obtained when the initial <a>setup a UPnP Events Subscription</a> action occurred.
richt@239
  1583
        </p>
richt@239
  1584
      </section>
richt@239
  1585
      <section>
danieldanciu@330
  1586
        <h5>
danieldanciu@330
  1587
          Discovery and Launch Protocol (<abbr title="Discovery and Launch Protocol">DIAL</abbr>)
danieldanciu@330
  1588
        </h5>
richt@371
  1589
        <p>
danieldanciu@330
  1590
          A user agent that implements DIAL service discovery MUST issue a <dfn>search request for DIAL-enabled
danieldanciu@330
  1591
          devices</dfn> against the user's current local network according to the full normative text and timing
danieldanciu@330
  1592
          provided in 'Section 1.3.2: Search request with M-SEARCH' detailed in [[!UPNP-DEVICEARCH11]].
danieldanciu@330
  1593
        </p>
danieldanciu@330
  1594
        <p>
richt@371
  1595
          Let <var>dial version</var> be the version number specified in the <a>valid service type</a> token. Let
richt@371
  1596
          <var>dial search target</var> be the concatentation of the
danieldanciu@330
  1597
          <code>urn:dial-multiscreen-org:service:dial:</code> string constant with the <var>dial version</var>
richt@332
  1598
          (currently, <var>dial version</var> can only be <code>1</code>)
danieldanciu@330
  1599
        </p>
danieldanciu@330
  1600
        <p>
richt@371
  1601
          The user agent MUST issue all <a title="search request for DIAL devices">search requests for DIAL devices</a>
richt@371
  1602
          with a HTTP request line equal to <code>M-SEARCH * HTTP/1.1</code>, with a HOST header equal to the reserved
richt@371
  1603
          multicast address and port of <code>239.255.255.250:1900</code>, a MAN header equal to
richt@371
  1604
          <code>ssdp:discover</code>, an ST header equal to <var>dial search target</var> and a user-agent defined MX
richt@371
  1605
          header equal to a <dfn>maximum DIAL advertisement response wait time</dfn> value between <code>1</code> and
richt@371
  1606
          <code>5</code> seconds.
danieldanciu@330
  1607
        </p>
danieldanciu@330
  1608
        <p>
danieldanciu@330
  1609
          The user agent MUST listen for any incoming responses to a <a>search request for DIAL devices</a>.
danieldanciu@330
  1610
        </p>
danieldanciu@330
  1611
        <p>
richt@371
  1612
          For each HTTP Response following an initial <a>search request for DIAL devices</a> sent on a <a>standard UPnP
richt@371
  1613
          address and port</a> the user agent MUST run the following steps:
danieldanciu@330
  1614
        </p>
danieldanciu@330
  1615
        <ol class="rule">
richt@371
  1616
          <li>If the HTTP Response is not a HTTP 200 OK response then this response is invalid and the user agent MUST
richt@371
  1617
          discard this response, abort any remaining steps and return. The user agent MAY issue a new <a>search request
richt@371
  1618
          for DIAL devices</a> as a result of this error occurring.
danieldanciu@330
  1619
          </li>
richt@332
  1620
          <li>If the <a>maximum DIAL advertisement response wait time</a> has been exceeded since the initial <a>search
danieldanciu@330
  1621
          request for DIAL devices</a> was sent then the <a>HTTP Response</a> is invalid and the user agent MUST
danieldanciu@330
  1622
          discard this response, abort any remaining steps and return. The user agent MAY stop listening for responses
richt@371
  1623
          from the current <a>search request for DIAL devices</a> as a result of this error occurring. Equally, the
richt@371
  1624
          user agent MAY issue a new <a>search request for DIAL devices</a> as a result of this error occurring.
danieldanciu@330
  1625
          </li>
danieldanciu@330
  1626
          <li>Let <var>dial device</var> be an Object with a property for each HTTP header received in the <a>HTTP
danieldanciu@330
  1627
          Response</a>, with each key being the name of a HTTP response header and each value being that HTTP response
danieldanciu@330
  1628
          header's value.
danieldanciu@330
  1629
          </li>
danieldanciu@330
  1630
          <li>If <var>dial device</var> does not contain at least one <var>CACHE-CONTROL</var> entry, at least one
danieldanciu@330
  1631
          <var>USN</var> entry, at least one <var>ST</var> entry and at least one <var>LOCATION</var> entry or the
richt@371
  1632
          value of its <var>ST</var> entry is not <var>dial search target</var>, then the <a>HTTP Response</a> is
richt@371
  1633
          invalid and the <a>user agent</a> MUST discard this response, abort any remaining steps and return.
danieldanciu@330
  1634
          </li>
danieldanciu@330
  1635
          <li>The user agent MUST run the rule for <a>obtaining a UPnP Device Description File</a> passing in the first
danieldanciu@330
  1636
          occurrence of <var>LOCATION</var> from <var>dial device</var> as the <var>device descriptor URL</var>
danieldanciu@330
  1637
          argument and the first occurrence of <var>USN</var> from <var>dial device</var> as the <var>device
danieldanciu@330
  1638
          identifier</var> argument and the first occurrence of <var>CACHE-CONTROL</var> from <var>dial device</var>
danieldanciu@330
  1639
          (minus the leading string of <code>max-age=</code>) as the <var>device expiry</var> argument.
danieldanciu@330
  1640
          </li>
danieldanciu@330
  1641
        </ol>
danieldanciu@330
  1642
        <p>
richt@332
  1643
          The rule for <dfn>obtaining a DIAL Device Description File</dfn> is the process of obtaining the contents of
danieldanciu@330
  1644
          a standard UPnP Device Description [[!UPNP-DEVICEARCH11]] from a URL-based resource. This rule takes three
danieldanciu@330
  1645
          arguments - <var>device descriptor URL</var>, <var>device identifier</var> and <var>device expiry</var> - and
danieldanciu@330
  1646
          when called the user agent MUST run the following steps:
danieldanciu@330
  1647
        </p>
danieldanciu@330
  1648
        <ol class="rule">
danieldanciu@330
  1649
          <li>Let <var>device descriptor file</var> contain the contents of the file located at the URL provided in
danieldanciu@330
  1650
          <var>device descriptor URL</var> obtained according to the rules defined in 'Section 2.11: Retrieving a
danieldanciu@330
  1651
          description using HTTP' in [[!UPNP-DEVICEARCH11]].
danieldanciu@330
  1652
          </li>
danieldanciu@330
  1653
          <li>Let <var>application url</var> be the value of the first occurrence of the <code>Application-URL</code>
richt@371
  1654
          response header field obtained according to the rules defined in 'Section 5.4: Device Description Response'
richt@371
  1655
          in [<a href="https://sites.google.com/a/dial-multiscreen.org/dial/dial-protocol-specification">DIAL</a>]
danieldanciu@330
  1656
          </li>
danieldanciu@330
  1657
          <li>If the value provided in <var>device descriptor URL</var> cannot be resolved as a reachable URL on the
richt@371
  1658
          current network or the <var>device descriptor file</var> remains empty or <var>application url</var> is
richt@371
  1659
          undefined then it is invalid and the <a>user agent</a> MUST abort any remaining steps and return.
danieldanciu@330
  1660
          </li>
danieldanciu@330
  1661
          <li>Run the following steps to add the newly discovered DIAL service:
danieldanciu@330
  1662
            <ol class="rule">
danieldanciu@330
  1663
              <li>Let <var>network service record</var> be a new Object consisting of the following empty properties:
danieldanciu@330
  1664
              <code>id</code>, <code>deviceId</code>, <code>name</code>, <code>type</code>, <code>url</code>,
danieldanciu@330
  1665
              <code>expiryTimestamp</code>.
danieldanciu@330
  1666
              </li>
danieldanciu@330
  1667
              <li>Set <var>network service record</var>'s <code>id</code> property to the first occurrence of the
danieldanciu@330
  1668
              <code>&lt;UDN&gt;</code> element in the <var>descriptor file</var> prefixed with the <code>dial:</code>
danieldanciu@330
  1669
              string constant
danieldanciu@330
  1670
              </li>
danieldanciu@330
  1671
              <li>Set <var>network service record</var>'s <code>deviceId</code> property to the value of <var>device
danieldanciu@330
  1672
              identifier</var>.
danieldanciu@330
  1673
              </li>
danieldanciu@330
  1674
              <li>Set <var>network service record</var>'s <code>name</code> property to the string value of the first
danieldanciu@330
  1675
              occurrence of the <code>&lt;friendlyName&gt;</code> element in the <var>descriptor file</var>.
danieldanciu@330
  1676
              </li>
danieldanciu@330
  1677
              <li>Set <var>network service record</var>'s <code>type</code> property to <var>dial search target</var>.
danieldanciu@330
  1678
              </li>
richt@371
  1679
              <li>Set <var>network service record</var>'s <code>url</code> property to the string value of the
richt@371
  1680
              <var>application url</var>.
danieldanciu@330
  1681
              </li>
danieldanciu@330
  1682
              <li>Set <var>network service record</var>'s <code>expiryTimestamp</code> property to the value of the
danieldanciu@330
  1683
              current date, in UTC timestamp format, plus the value of <var>device expiry</var>.
danieldanciu@330
  1684
              </li>
danieldanciu@330
  1685
              <li>Run the general rule for <a>adding an available service</a>, passing in the current <var>network
danieldanciu@330
  1686
              service record</var> as the only argument.
danieldanciu@330
  1687
              </li>
danieldanciu@330
  1688
            </ol>
danieldanciu@330
  1689
          </li>
danieldanciu@330
  1690
        </ol>
danieldanciu@330
  1691
      </section>
danieldanciu@330
  1692
      <section>
richt@239
  1693
        <h3>
richt@239
  1694
          Network Topology Monitoring
richt@239
  1695
        </h3>
richt@239
  1696
        <div>
richt@180
  1697
          <p>
richt@376
  1698
            When the <a>user agent</a> detects that the user has dropped from a connected network then, for each
richt@377
  1699
            <var>existing service record</var> in the <a>list of available service records</a> discovered via that
richt@377
  1700
            network connection, the <a>user agent</a> MUST run the general rule for <a>removing an available
richt@377
  1701
            service</a> passing in each <var>existing service record</var>'s <code>id</code> property as the only
richt@377
  1702
            argument for each call.
richt@180
  1703
          </p>
richt@180
  1704
          <p>
richt@239
  1705
            When the <a>user agent</a> detects that the user has connected to a new network or reconnected to an
richt@250
  1706
            existing network, then it SHOULD restart its discovery mechanisms as defined in the <a href=
richt@250
  1707
            "#service-discovery">Service Discovery</a> section of this specification, maintaining the existing <a>list
richt@250
  1708
            of active service managers</a> currently in use.
richt@180
  1709
          </p>
richt@239
  1710
        </div>
richt@180
  1711
      </section>
richt@239
  1712
    </section>
richt@239
  1713
    <section>
richt@239
  1714
      <h3>
richt@239
  1715
        Events Summary
richt@239
  1716
      </h3>
richt@191
  1717
      <p>
richt@239
  1718
        The following events are dispatched on the <a href="#networkservices"><code>NetworkServices</code></a> and/or
richt@239
  1719
        <a href="#networkservice"><code>NetworkService</code></a> objects:
richt@191
  1720
      </p>
richt@243
  1721
      <table border="1">
richt@180
  1722
        <thead>
richt@180
  1723
          <tr>
richt@180
  1724
            <th>
richt@239
  1725
              <span>Event name</span>
richt@238
  1726
            </th>
richt@238
  1727
            <th>
richt@238
  1728
              <span>Interface</span>
richt@238
  1729
            </th>
richt@238
  1730
            <th>
richt@238
  1731
              <span>Dispatched when...</span>
richt@238
  1732
            </th>
richt@238
  1733
          </tr>
richt@238
  1734
        </thead>
richt@238
  1735
        <tbody>
richt@238
  1736
          <tr>
richt@238
  1737
            <td>
richt@239
  1738
              <dfn id="event-serviceavailable"><code>serviceavailable</code></dfn>
richt@238
  1739
            </td>
richt@238
  1740
            <td>
richt@239
  1741
              <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@239
  1742
                  class="externalDFN"><code>Event</code></a>
richt@238
  1743
            </td>
richt@238
  1744
            <td>
richt@387
  1745
              When a <a>new service</a> that matches one of the <a>requested type tokens</a> is found in the current
richt@387
  1746
              network.
richt@238
  1747
            </td>
richt@238
  1748
          </tr>
richt@238
  1749
          <tr>
richt@238
  1750
            <td>
richt@239
  1751
              <dfn id="event-serviceunavailable"><code>serviceunavailable</code></dfn>
richt@238
  1752
            </td>
richt@238
  1753
            <td>
richt@239
  1754
              <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@239
  1755
                  class="externalDFN"><code>Event</code></a>
richt@238
  1756
            </td>
richt@238
  1757
            <td>
richt@387
  1758
              When an <a>existing service</a> that matches one of the <a>requested type tokens</a> gracefully leaves or
richt@239
  1759
              expires from the current network.
richt@238
  1760
            </td>
richt@238
  1761
          </tr>
richt@238
  1762
          <tr>
richt@238
  1763
            <td>
richt@239
  1764
              <dfn id="event-serviceonline"><code>serviceonline</code></dfn>
richt@238
  1765
            </td>
richt@238
  1766
            <td>
richt@239
  1767
              <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@239
  1768
                  class="externalDFN"><code>Event</code></a>
richt@238
  1769
            </td>
richt@238
  1770
            <td>
richt@387
  1771
              When a <a>current service</a> renews its service registration within the current network.
richt@238
  1772
            </td>
richt@238
  1773
          </tr>
richt@238
  1774
          <tr>
richt@238
  1775
            <td>
richt@239
  1776
              <dfn id="event-serviceoffline"><code>serviceoffline</code></dfn>
richt@238
  1777
            </td>
richt@238
  1778
            <td>
richt@239
  1779
              <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@239
  1780
                  class="externalDFN"><code>Event</code></a>
richt@238
  1781
            </td>
richt@238
  1782
            <td>
richt@387
  1783
              When a <a>current service</a> gracefully leaves or otherwise expires from the current network.
richt@238
  1784
            </td>
richt@238
  1785
          </tr>
richt@238
  1786
          <tr>
richt@238
  1787
            <td>
richt@239
  1788
              <dfn id="event-notify"><code>notify</code></dfn>
richt@238
  1789
            </td>
richt@238
  1790
            <td>
richt@239
  1791
              <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event"
richt@239
  1792
                  class="externalDFN"><code>Event</code></a>
richt@238
  1793
            </td>
richt@238
  1794
            <td>
richt@239
  1795
              When a valid UPnP Events Subscription Message is received on a <a>user-agent generated callback url</a>
richt@387
  1796
              for a <a>current service</a>. This event never fires for Zeroconf-based services.
richt@238
  1797
            </td>
richt@238
  1798
          </tr>
richt@238
  1799
        </tbody>
richt@238
  1800
      </table>
richt@239
  1801
    </section>
richt@239
  1802
    <section>
richt@239
  1803
      <h3>
richt@239
  1804
        Garbage collection
richt@239
  1805
      </h3>
richt@180
  1806
      <p>
richt@250
  1807
        A user agent MUST only garbage collect a <a><code>NetworkServices</code></a> object and remove its entry from
richt@371
  1808
        the <a>list of active service managers</a> when the user has navigated away from the <a href=
richt@371
  1809
        "http://www.whatwg.org/specs/web-apps/current-work/complete/browsers.html#entry-script"
richt@371
  1810
           class="externalDFN">entry script</a>'s <a href=
richt@371
  1811
           "http://www.whatwg.org/specs/web-apps/current-work/complete/origin-0.html#origin"
richt@371
  1812
           class="externalDFN">origin</a> in which the current <a><code>NetworkServices</code></a> object was provided.
richt@250
  1813
      </p>
richt@250
  1814
      <p>
richt@250
  1815
        A user agent MUST NOT garbage collect individual <a><code>NetworkService</code></a> objects until their parent
richt@250
  1816
        <a><code>NetworkServices</code></a> object has been garbage collected.
richt@250
  1817
      </p>
richt@250
  1818
      <p>
richt@250
  1819
        A user agent MUST garbage collect the <a><code>NetworkService</code></a> <a>indexed properties</a> of a
richt@397
  1820
        <a><code>NetworkServices</code></a> object, passing each indexed property's <code>id</code> attribute as the
richt@437
  1821
        only argument to the rule for <a>removing an available service</a>, when that
richt@437
  1822
        <a><code>NetworkServices</code></a> object itself has been garbage-collected.
richt@180
  1823
      </p>
richt@239
  1824
    </section>
richt@180
  1825
    <section>
richt@239
  1826
      <h3>
richt@239
  1827
        Use Cases and Requirements
richt@239
  1828
      </h3>
richt@239
  1829
      <p>
richt@239
  1830
        This section covers what the requirements are for this API, as well as illustrates some use cases.
richt@239
  1831
      </p>
richt@180
  1832
      <ul class="rule">
richt@239
  1833
        <li>Once a user has given permission, user agents should provide the ability for Web pages to communicate
richt@239
  1834
        directly with a Local-networked Service.
richt@239
  1835
          <ul class="rule">
richt@239
  1836
            <li>Example: A web-based TV remote control. A Web page wants to control the current user's TV, changing the
richt@239
  1837
            programming shown or increasing/decreasing/muting the volume of the Local-networked Device. The Web page
richt@239
  1838
            requests a service type that is known to be implemented by television sets to which it has the application
richt@239
  1839
            logic to communicate. Local devices providing the request service types are discovered and presented to the
richt@239
  1840
            user for authorization. The user selects one or more of the discovered television sets to be accessible to
richt@239
  1841
            the current Web page and then clicks 'Share'. The Web page can now communicate directly with the
richt@239
  1842
            user-authorized Local-networked services.
richt@180
  1843
            </li>
richt@239
  1844
          </ul>
richt@239
  1845
        </li>
richt@239
  1846
        <li>Web pages should be able to communicate with Local-networked Services using the messaging channel supported
richt@239
  1847
        by those Devices.
richt@239
  1848
          <ul class="rule">
richt@239
  1849
            <li>Example: A Web page advertises that it is capable of controlling multiple Home Media Servers. The user
richt@239
  1850
            can select their Home Media Server type from a drop-down list, at which point the Web page sends a request
richt@239
  1851
            to the user agent to connect with the associated service type of the Home Media Server. The Media Server
richt@239
  1852
            selected implements a Web Socket channel for bi-directional service communication and so the Web page opens
richt@239
  1853
            a web socket to the requested Media Server and can communicate as required via that appropriate channel.
richt@180
  1854
            </li>
richt@239
  1855
          </ul>
richt@239
  1856
        </li>
richt@239
  1857
        <li>Web pages should be able to communicate with Local-networked Services using the messaging format supported
richt@239
  1858
        by those Devices.
richt@239
  1859
          <ul class="rule">
richt@239
  1860
            <li>Example: A Web page advertises that it is capable of interacting with and controlling multiple types of
richt@239
  1861
            Home Media Server. The user can select their Home Media Server type from a drop-down list or known Media
richt@239
  1862
            Servers, at which point the Web page sends a request to the user agent to connect with the associated
richt@240
  1863
            service type (and, optionally, the associated event type) of the Home Media Server. The communication
richt@239
  1864
            protocols supported by Home Media Servers typically vary between UPnP, JSON-RPC, Protocol Buffers or other
richt@239
  1865
            messaging formats depending on the Home Media Server requested. The Web page is able to communicate with
richt@239
  1866
            the user-selected Home Media Server in the messaging format supported by that Device, which, in this
richt@239
  1867
            example is a simple key/value pair text format.
richt@180
  1868
            </li>
richt@239
  1869
          </ul>
richt@239
  1870
        </li>
richt@239
  1871
        <li>Web pages should not be able to communicate with Local-networked Services that have not been authorized by
richt@239
  1872
        the user thereby maintaining the user's privacy.
richt@239
  1873
          <ul class="rule">
richt@239
  1874
            <li>Example: A Web page requests access to one type of Local-networked service. The user authorizes access
richt@239
  1875
            to that particular service. Other services running on that same device, and on other devices within the
richt@239
  1876
            network, should not be accessible to the current Web page.
richt@180
  1877
            </li>
richt@239
  1878
          </ul>
richt@239
  1879
        </li>
richt@239
  1880
        <li>A user should be able to share one or more Local-networked Services based on a particular service type
richt@239
  1881
        request from a Web page.
richt@239
  1882
          <ul class="rule">
richt@239
  1883
            <li>Example: A Web page is capable of interacting with a specific profile of Local-networked Service. As
richt@239
  1884
            such, it makes a request to the user agent to access those services, of which multiple matches are found.
richt@239
  1885
            The user is capable of selecting one or more of the discovered services to share with the Web page. The Web
richt@239
  1886
            page can then implement a drag-and-drop interface for the user to drag specific actions on to one or more
richt@239
  1887
            of the authorized Local-networked Services.
richt@239
  1888
            </li>
richt@239
  1889
          </ul>
richt@239
  1890
        </li>
richt@239
  1891
        <li>User agents should provide an API exposed to script that exposes the features above. The user is notified
richt@239
  1892
        by UI anytime interaction with Local-networked Services is requested, giving the user full ability to cancel or
richt@239
  1893
        abort the transaction. The user selects the Local-networked Services to be connected to the current Web page,
richt@239
  1894
        and can cancel these at any time. No invocations to these APIs occur silently without user intervention.
richt@239
  1895
        </li>
richt@180
  1896
      </ul>
richt@180
  1897
    </section>
richt@239
  1898
    <section class="informative appendix">
richt@239
  1899
      <h3>
richt@239
  1900
        Examples
richt@239
  1901
      </h3>
richt@239
  1902
      <div class="example">
richt@239
  1903
        <p>
richt@239
  1904
          This sample code exposes a button. When clicked, this button is disabled and the user is prompted to offer a
richt@239
  1905
          network service. The user may also select multiple network services. When the user has authorized a network
richt@239
  1906
          service to be connected to the web page then the web page issues a simple command to get a list of all the
richt@239
  1907
          albums stored on the connected media player service.
richt@239
  1908
        </p>
richt@239
  1909
        <p>
richt@239
  1910
          The button is re-enabled only when the connected network service disconnects for whatever reason (the service
richt@239
  1911
          becomes unavailable on the network, the user disconnects from their current network or the user revokes
richt@239
  1912
          access to the service from the current web page). At this point the user can re-click the button to select a
richt@239
  1913
          new network service to connect to the web page and the above steps are repeated.
richt@239
  1914
        </p>
richt@239
  1915
        <p>
richt@239
  1916
          The provided service type identifier and service interaction used in this example is based on the
richt@239
  1917
          well-defined service type and messaging format supported by the <a href="http://xbmc.org/about/">XBMC Media
richt@239
  1918
          Server</a>.
richt@239
  1919
        </p>
richt@239
  1920
        <hr>
richt@239
  1921
        <pre class="highlight">
richt@239
  1922
&lt;input type="button" value="Start" onclick="start()" id="startBtn"/&gt;
richt@239
  1923
&lt;div id="debugconsole"&gt;&lt;/div&gt;
richt@180
  1924
richt@239
  1925
&lt;script&gt;
richt@180
  1926
 var startBtn = document.getElementById('startBtn'),
richt@180
  1927
     debug = document.getElementById('debugconsole');
richt@180
  1928
richt@180
  1929
 function start() {
richt@180
  1930
   if(navigator.getNetworkServices) {
richt@438
  1931
      navigator.getNetworkServices('zeroconf:_xbmc-jsonrpc._tcp').then(gotXBMCService).catch(error);
richt@180
  1932
      startBtn.disabled = true;
richt@180
  1933
   } else {
richt@191
  1934
      debug.innerHTML += "&lt;br&gt;Service Discovery not supported!";
richt@180
  1935
   }
richt@180
  1936
 }
richt@180
  1937
richt@180
  1938
 function gotXBMCService(services) {
richt@180
  1939
richt@180
  1940
// Listen for service disconnect messages
richt@180
  1941
richt@191
  1942
   services[0].addEventListener('serviceoffline', function ( e ) {
richt@239
  1943
       debug.innerHTML += "&lt;br&gt;" + services[0].name + " disconnected.";
richt@180
  1944
       startBtn.disabled = false;
richt@180
  1945
   }, false);
richt@180
  1946
richt@180
  1947
// Send a service message to get albums list (and process the service response)
richt@180
  1948
richt@180
  1949
   var svcXhr = new XMLHttpRequest();
richt@240
  1950
   svcXhr.open("POST", services[0].url + "/getAlbums"); // services[0].url and its sub-resources have been
richt@180
  1951
                                                        // whitelisted for cross-site XHR use in this
richt@180
  1952
                                                        // current browsing context.
richt@180
  1953
richt@180
  1954
   svcXhr.setRequestHeader('Content-Type', 'application/json-rpc');
richt@180
  1955
richt@180
  1956
   svcXhr.addEventListener('readystatechange', function ( response ) {
richt@180
  1957
     if( response.readyState != 4 || response.status != 200 )
richt@180
  1958
        return;
richt@239
  1959
     debug.innerHTML += "&lt;br&gt;" + services[0].name + " response received: ";
richt@180
  1960
     debug.textContent += JSON.parse(response.responseText);
richt@180
  1961
   }, false);
richt@180
  1962
richt@180
  1963
   var svcMsg = [
richt@180
  1964
     { "jsonrpc": "2.0", "method": "AudioLibrary.GetAlbums", "params": { "genreid": -1,
richt@180
  1965
         "artistid": -1, "start": -1, "end": -1 }, "id": "1" }
richt@180
  1966
   ];
richt@180
  1967
richt@180
  1968
   svcXhr.send(JSON.stringify(svcMsg));
richt@239
  1969
   debug.innerHTML += "&lt;br&gt;" + services[0].name + " request sent: ";
richt@180
  1970
   debug.textContent += JSON.stringify(svcMsg);
richt@180
  1971
richt@180
  1972
 }
richt@180
  1973
richt@180
  1974
 function error( err ) {
richt@239
  1975
   debug.innerHTML += "&lt;br&gt;An error occurred obtaining a local network service.";
richt@180
  1976
   startBtn.disabled = false;
richt@180
  1977
 }
richt@239
  1978
&lt;/script&gt;
richt@239
  1979
</pre>
richt@239
  1980
      </div>
richt@239
  1981
      <div class="example">
richt@239
  1982
        <p>
richt@239
  1983
          This sample exposes a drop-down list containing a number of common Home-based audio devices. When the user
richt@239
  1984
          selects an audio device from the list provided, they are prompted to authorize a network service based on the
richt@239
  1985
          service type requested. The user may also select multiple network services matching the selected service
richt@239
  1986
          type. In this example, the user selects their make as being <var>Sony</var> and their model as being
richt@239
  1987
          <var>Bravia S1000</var> from which the Web page can derive a service type
richt@239
  1988
          (<var>urn:schemas-upnp-org:service:RenderingControl:1</var>).<br>
richt@239
  1989
          <br>
richt@239
  1990
          Once the user has authorized the device, the web page sends a simple mute command according to the messaging
richt@239
  1991
          format supported by the device.
richt@239
  1992
        </p>
richt@239
  1993
        <hr>
richt@239
  1994
        <pre class="highlight">
richt@239
  1995
&lt;select name="make" id="make"&gt;
richt@180
  1996
  &lt;option selected="selected" disabled="disabled"&gt;Select make&lt;/option&gt;
richt@180
  1997
  &lt;option&gt;Sony&lt;/option&gt;
richt@180
  1998
  &lt;option&gt;Philips&lt;/option&gt;
richt@180
  1999
  &lt;option&gt;Alba&lt;/option&gt;
richt@180
  2000
&lt;/select&gt;
richt@180
  2001
&lt;select name="model" id="model"&gt;&lt;/select&gt;
richt@180
  2002
&lt;div id="debugconsole"&gt;&lt;/div&gt;
richt@180
  2003
richt@180
  2004
&lt;script&gt;
richt@180
  2005
  var debug = document.getElementById('debugconsole');
richt@180
  2006
richt@180
  2007
  var models = {
richt@180
  2008
    "Sony": [
richt@180
  2009
      {"name": "Bravia TV S1000", "type": "upnp", "service": "urn:schemas-upnp-org:service:RenderingControl:1" },
richt@180
  2010
      {"name": "Bravia TV S2000", "type": "zeroconf", "service": "_mediarenderer._http._tcp" },
richt@180
  2011
      {"name": "HiFi WD10", "type": "upnp", "service": "urn:schemas-upnp-org:service:RenderingControl:1" }
richt@180
  2012
    ],
richt@180
  2013
    "Philips": [ /* ... */ ],
richt@180
  2014
    "Alba": [ /* ... */ ]
richt@180
  2015
  };
richt@180
  2016
richt@180
  2017
  var makeEl = document.getElementById("make"),
richt@180
  2018
      modelEl = document.getElementById("model");
richt@180
  2019
richt@180
  2020
  makeEl.addEventListener('change', function() {
richt@180
  2021
    modelEl.innerHTML = ""; // reset
richt@180
  2022
    var defaultOption = document.createElement("option");
richt@180
  2023
    defaultOption.textContent = "Select model";
richt@180
  2024
    defaultOption.setAttribute("disabled", "disabled");
richt@180
  2025
    defaultOption.setAttribute("selected", "selected");
richt@180
  2026
    modelEl.appendChild(defaultOption);
richt@239
  2027
    for(var i = 0, l = models[makeEl.value].length; i &lt; l; i++) {
richt@180
  2028
      var option = document.createElement("option");
richt@180
  2029
      option.textContent = models[makeEl.value][i]["name"];
richt@180
  2030
      option.setAttribute("value", models[makeEl.value][i]["type"] + ":" + models[makeEl.value][i]["service"]);
richt@180
  2031
      modelEl.appendChild(option);
richt@180
  2032
    }
richt@180
  2033
  }, false);
richt@180
  2034
richt@180
  2035
  modelEl.addEventListener('change', function() {
richt@239
  2036
    if(navigator.getNetworkServices &amp;&amp;
richt@180
  2037
         modelEl.value == "upnp:urn:schemas-upnp-org:service:RenderingControl:1") {
richt@437
  2038
      var servicesPromise = navigator.getNetworkServices(modelEl.value).then(successCallback, errorCallback);
richt@180
  2039
    } else if (modelEl.value == "zeroconf:_mediarenderer._http._tcp") {
richt@180
  2040
      debug.innerHTML += "&lt;br&gt;Service type is not implemented by this application.";
richt@180
  2041
    } else {
richt@180
  2042
      debug.innerHTML += "&lt;br&gt;Service Discovery is not supported!";
richt@180
  2043
    }
richt@180
  2044
  }, false);
richt@180
  2045
&lt;/script&gt;
richt@180
  2046
richt@180
  2047
&lt;script&gt;
richt@180
  2048
  function successCallback( services ) {
richt@180
  2049
richt@191
  2050
  // Listen for service push notification messages
richt@180
  2051
richt@191
  2052
    services[0].addEventListener('notify', function ( msg ) {
richt@239
  2053
         debug.innerHTML += "&lt;br&gt;" + services[0].name + " event received: ";
richt@180
  2054
         debug.textContent += msg.data;
richt@180
  2055
    }, false);
richt@180
  2056
richt@180
  2057
 // Send a control signal to mute the service audio
richt@180
  2058
richt@180
  2059
    var svcXhr = new XMLHttpRequest();
richt@180
  2060
    svcXhr.open("POST", services[0].url); // services[0].url and its
richt@240
  2061
                                          // sub-resources have been whitelisted for
richt@180
  2062
                                          // cross-site XHR use in this current
richt@180
  2063
                                          // browsing context.
richt@180
  2064
richt@180
  2065
    svcXhr.setRequestHeader('SOAPAction', 'urn:schemas-upnp-org:service:RenderingControl:1#SetMute');
richt@180
  2066
    svcXhr.setRequestHeader('Content-Type', 'text/xml; charset="utf-8";');
richt@180
  2067
richt@180
  2068
    svcXhr.onreadystatechange = function ( response ) {
richt@180
  2069
      if( response.readyState != 4 || response.status != 200 )
richt@180
  2070
        return;
richt@180
  2071
      debug.innerHTML += "&lt;br&gt;" + services[0].name + " response received: ";
richt@180
  2072
      debug.textContent += response.responseXML;
richt@180
  2073
    }
richt@180
  2074
richt@180
  2075
    // Service messaging to mute the provided service
richt@180
  2076
    var svcMsg = '&lt;?xml version="1.0" encoding="utf-8"?&gt;' +
richt@180
  2077
                 '&lt;s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" ' +
richt@180
  2078
                   'xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"&gt;' +
richt@180
  2079
                   '&lt;s:Body&gt;' +
richt@180
  2080
                     '&lt;u:SetMute xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"&gt;' +
richt@180
  2081
                       '&lt;InstanceID&gt;0&lt;/InstanceID&gt;' +
richt@180
  2082
                       '&lt;Channel&gt;Master&lt;/Channel&gt;' +
richt@180
  2083
                       '&lt;DesiredMute&gt;true&lt;/DesiredMute&gt;' +
richt@180
  2084
                     '&lt;/u:SetMute&gt;' +
richt@180
  2085
                   '&lt;/s:Body&gt;' +
richt@180
  2086
                 '&lt;/s:Envelope&gt;';
richt@180
  2087
richt@180
  2088
    svcXhr.send(svcMsg);
richt@180
  2089
    debug.innerHTML += "&lt;br&gt;" + services[0].name + " request sent: ";
richt@180
  2090
    debug.textContent += svcMsg;
richt@180
  2091
  }
richt@180
  2092
richt@180
  2093
  function errorCallback( error ) {
richt@180
  2094
    debug.innerHTML += "&lt;br&gt;An error occurred: " + error.code;
richt@180
  2095
  }
richt@239
  2096
&lt;/script&gt;
richt@239
  2097
</pre>
richt@239
  2098
      </div>
richt@239
  2099
    </section>
richt@180
  2100
    <section>
richt@239
  2101
      <h3>
richt@239
  2102
        Acknowledgements
richt@239
  2103
      </h3>
richt@239
  2104
      <p>
richt@239
  2105
        Thanks are expressed by the editor to the following individuals for their feedback on this specification to
richt@239
  2106
        date (in alphabetical order):<br>
richt@239
  2107
        <br>
richt@239
  2108
        Gar Bergstedt, Lars-Erik Bolstad, Cathy Chan, Hari G Kumar, Bob Lund, Giuseppe Pascale, Marcin Simonides,
richt@239
  2109
        Clarke Stevens, Christian Söderström, Mark Vickers.
richt@239
  2110
      </p>
richt@239
  2111
      <p>
richt@239
  2112
        Thanks are also expressed by the editor to the following organizations and groups for their support in
richt@239
  2113
        producing this specification to date (in alphabetical order):<br>
richt@239
  2114
        <br>
richt@239
  2115
        CableLabs, Opera Software ASA, W3C Device APIs Working Group, W3C Web and TV Interest Group.
richt@239
  2116
      </p>
richt@180
  2117
    </section>
richt@239
  2118
  </body>
richt@180
  2119
</html>