Re: [discovery-api] Consolidated comments and questions

Hi all, wrote:
> As promised at the DAP call last week, here is a collection of
> comments and
> questions on Network Service Discovery APIs that have not been addressed
> or resolved. I've grouped them into three categories - technical
> comments,
> feature requests, and questions and clarifications. Hopefully this
> helps in
> focusing future discussions one way or another.

Thanks for consolidating these comments and questions! Let me start by 
going through each of the items below and let's pick up the discussion here.

> I tried to distill some of the issues where I can, but left most of
> them in
> the way
> that they were initially brought up. Hence the length of this message.

If you wish to reply to anything below, please do so in-line, removing 
the rest of the message that is not relevant to your specific feedback.

> If I inadvertently left out anything, please kindly add to the list.
> Thanks.
> -------------------
> Comments and questions on Network Service Discovery APIs (4 Oct, 2012
> draft
> [0])
> A. Technical comments on the current draft
> 1. Explicit user permission is required for every device upon each
> getNetworkServices() call. Should that be changed? From Greg [1]:
> [[The user verification steps are good as a semantic point, I think,
> but the
> spec seems too insistent that the user be prompted for every discovery
> interaction. If they have a TV they are controlling, why not enable
> that to
> be used by default? I think the thinking from comparing web intents and
> registerProtocolHandler will prevail -- the set of APIs that allow
> users to
> select handlers, services, etc. will be presented to the user in a
> uniform
> way by UAs, and so the same defaulting policies should apply to all.]]
> Rich's response [2]:
> [[That's a good point. The spec doesn't yet have wording to this
> effect. I
> expect we could add it at Step 13 of the getNetworkServices algorithm,
> changing it to something like "Optionally, e.g. based on a
> previously-established user preference, for security reasons, or due to
> platform limitations, the user agent may "... return a pre-defined
> successCallback or throw an errorCallback. The wording here would need
> some
> work ;)]]
> Greg's suggestion [3]:
> [[4.1 ... When the getNetworkServices(type, successCallback[,
> errorCallback]) method is called, the user agent must run the following
> steps:
> ...
> 10. The user agent must prompt the user in a user-agent-specific
> manner for
> permission ...
> I suggest changing this to something along the lines of "The user
> agent must
> not provide the entry script's origin [...] without prior permission
> given
> by the user." or something like that to communicat that the user and
> UA can
> team up to make defaulting possible -- the point being the UA has a
> responsibility to the user not to do things without permission, but
> they can
> get an understanding of that permission without explicit prompting at
> every
> invocation.]]

I've updated the specification to incorporate this feedback:

> 2. In the introductory text of 7 Service Discovery, in the definition
> of "list
> of available service records", s/at any given time/at the current
> time/ to
> match the change made to "list of active service managers".


> 3. Unnecessary requirement on UA to issue UPnP search requests with
> search
> target of "upnp:rootdevice". From Cathy [4], [6]:
> In the introductory text of 7.2 Simple Service Discovery Protocol,
> [[The user agent must issue all search requests for UPnP root devices
> with a
> HTTP request line equal to M-SEARCH * HTTP/1.1, with a HOST header
> equal to
> the reserved multicast address and port of, a MAN
> header
> equal to ssdp:discover, an ST header equal to upnp:rootdevice and a
> user-agent
> defined MX header equal to a maximum UPnP advertisement response wait
> time
> value between 1 and 5 seconds.]]
> This requires UAs to always issue search requests for "upnp:rootdevice".
> However, in cases where the UA invokes a search in response to a call to
> getNetworkServices() with a particular UPnP service type, the UA
> should be
> allowed to issue a search with the requested search target instead of
> the much
> broader "upnp:rootdevice" one. This would cause only the targeted
> services to
> respond (as opposed to all services responding and leaving it to the
> UA to
> filter out those that do not match).

Agreed and I've updated the specification accordingly:

> 4. Simplify algorithm for "adding an available service"? From Cathy [6]:
> [[Actually looking at the algorithm again, step 4.2.3 should be
> performed when
> the new service registration flag is *true*. In the case that the flag
> was
> false, the service was already in the list of available service records,
> meaning it must have already been online (by definition of the list of
> available service records). Thus, all the corresponding NetworkService
> objects
> within each NetworkServices object would also have had the online
> attribute
> set to true. There would be no need to change their online attributes
> and no
> need to dispatch the serviceonline events. On the other hand, in the
> case that
> the new service registration flag is true, and a matching service
> record is
> found in the service manager, the service must have been previously
> discovered, the service record removed from the list of available service
> record (because it went offline), and was retained in the service
> manager and
> marked as offline (per step in 'removing an available
> service'). Now
> that the service is back online, the matching record in the service
> manager
> needs to be marked as online and the serviceonline event be
> dispatched. (Note
> also that the condition that the online attribute was previously false is
> unnecessary, as it must always be the case.)

I had to read this around 10 times but finally I figured it out ;)

I've updated the spec with changes to the algorithms as suggested:

> Furthermore, since steps 3 and 4 both apply only when the new service
> registration flag is true, one can simplify the algorithm by aborting
> at the
> end of step 2.3 (where an existing service record is found in the
> current list
> of available service records). In fact, the new service registration
> flag is
> not even needed at all, simplifying this even more.]]

I've incorporated this in to the commit provided above.

> 5. From Cathy [4]: In 7.2, in the steps for processing HTTP Requests,
> Step 3
> applies only to ssdp:alive messages (ssdp:byebye messages do not have the
> CACHE-CONTROL and LOCATION entries). It should start with "If the
> value of the NTS entry of the ssdp device is 'ssdp:alive'".


> 6. From Cathy [6]: In 7, in the steps for adding an available service,
> step 4
> determines if the network service record is of a type that the service
> manager
> would be
> interested in (and hence whether the servicesAvailable attribute needs
> to be
> updated and the serviceavailable event be sent). It would be more
> accurate to
> simply compare the network service record's type attribute with the type
> attribute that was used in the getNetworkServices API to create the
> particular
> service manager object. Consider the case where the web page invokes
> getNetworkServices with two types (A and B). At the time of the
> invocation,
> two service records of type A were found but nothing of type B was
> found. The
> associated service manager object would therefore have two service
> records,
> both of type A, but it (or the web page) would certainly still be
> interested
> in being notified if a new service of type B do become available later
> on.
> With the current algorithm, when a new service of type B is found by
> the UA,
> the service manager would not be made aware of it.

Excellent catch and fixed (also updated in the rule for 'removing an 
available service'):

> 7. From Cathy [6]: In 7, in the steps for removing an available
> service, step
> 2 attempts to unsubscribe from existing UPnP events subscriptions.
> However,
> event
> subscription is done once per each *authorized* service, i.e. per
> NetworkService object instances in service manager objects, and not per
> instance of the service record in the list of available service
> records. Thus
> step 2 should be a sub-step of 3.2.3.

I've made a few structural changes to how this algorithm is laid out 
that hopefully resolves this issue:

> 8. Network topology. From Youenn [7]:
> [[A device may have more than one ongoing network connection.
> If one network connection is dropped amongst several, only the service
> records
> that are related to the dropped network should probably be removed.
> First sentence in section 7.3 may be further precised on that respect.]]

Clarified the first sentence in 7.3:

> B. Feature requests
> 1. Unpack config information? From Greg [3]:
> [[Would it be more convenient to unpack that for the client in a
> strucured
> way? That is, it sounds like the opaque config string may only be
> useful if
> the client app already has knowledge of particular devices. Should the
> provide that identifier (unique device id?
> device descriptor doc?) in parsed form? Or are there too many or too much
> variation for that to make sense?

I believe there is too much variation in the data we can and may receive.

Add to that the complexities in converting XML to JSON and we start to 
dig ourselves a large hole rather quickly heading down this path IMO.

> I don't know that a special user opt-in for this info makes sense -- my
> question is more about what the client will use it for, and whether
> the UA
> can do a better job of presenting it, or if it'll be hard to use, should
> just not present it at all.]]

We should probably drop the .config attribute for privacy purposes. It 
doesn't actually add anything to the communication aspects of the API. 
All of that happens through the .url attribute on NetworkService objects.

It's something we need to discuss further so I've left the spec 
unchanged for now.

> 2. Expiration time of mDNS service record should either come from the
> service
> or be left up to implementation, and not mandated by the spec (currently
> 120ms). From Cathy [4].
> Also from Youenn [7]:
> [[120 seconds seems a pretty small value.
> Depending on the message types, the recommended TTL value is either 120
> seconds or 75 minutes as per the mdns spec.
> Would 75 minutes be more appropriate in that case?

That's quite a big difference from 120 seconds.

> More generally, a browser may have a precise knowledge of the TTL and may
> prefer using a value different from the one in the spec.
> Would it make sense to accommodate the rules accordingly?]]
> Rich indicated that the Zeroconf section will be reviewed and revised
> [5].

I'd be more comfortable mandating a short timeout, like the 120 seconds 
mentioned in the mDNS specification, to maintain a fresh services table 
and consistency across implementations (not to mention, simplicity). We 
*could* leave this up to implementations and I could therefore downgrade 
this to a SHOULD requirement, but I'm tempted to leave it as it is for 
in the interest of maintaining a healthy active services table.

I'm open to rewrite proposals here.

> 3. Use UPnP friendly name as From Cathy [8]:
> [[The attribute is supposed to be a
> "human-readable title
> for the service". Currently, for UPnP, it's defined to be the serviceId,
> which doesn't fit the intended purpose at all. I would suggest using the
> device's friendlyName in this attribute if it's intended to be a
> user-facing
> property.]]
> JCD is concerned about fingerprinting [9]. Cathy thinks as long as the
> information is provided after user consent, it should be ok [10].

The UPnP Friendly Name is only provided at the device-level, not at the 
individual services level. As such it doesn't seem it would make sense 
to use that for service naming (10 different services from the same 
device would each have the same names which is misleading IMO).

It would be great if there were something equivalent to 'friendly name' 
in the service description file (obtainable via the Service's SCPDURL 
element). Alas, there is no such thing.

> 4. Allow device type search (and more generally, other UPnP search
> strings)?
>> From Naoyuki Sato [11], [13] and Cathy [14]:
> It is typically more common for UPnP controller applications to search
> for
> device types than service types, as controllers tend to expose a
> device list
> for the user to select from.

The abstraction introduced by this specification is at the 
service-level. At no point would a user agent know what device types to 
search for since that is not a parameter that can be provided via the 
getNetworkServices() method.

I have updated the specification so implementations can search for 
'ssdp:all', 'upnp:rootdevice' or a valid service type token in their 
UPnP Search. I don't know how we could know to search for a specific 
device type in this specification. That would be a severe limitation on 
user choice in selecting services that match those requested by the page 
and favors the big players to promote and exclude existing and new 
devices from being discovered via this API.

The specification is deliberately device-neutral and service orientated.

> 5. Allow cross-domain access to additional UPnP device resources in
> addition
> to control URL? From Naoyuki Sato [11], [13]:
> The access white-list should be expanded to include additional UPnP
> resources
> such as device description page, service description page, which
> allows the
> web app to examine the actions and other details supported by a
> service, and
> device icons, which allow the web app to show the device icon to
> improve user
> experience.

That could be a good addition. We could add .icon to the NetworkService 
interface for example.

However, that would be a UPnP specific attribute. There is no easily 
addressable icon equivalent in mDNS AFAIK. If it only works half the 
time it's probably not worth adding.

> C. Questions and clarifications
> 1. Questions about multi-type query. From Youenn [7]:
> [[What is the benefit of having one single query with a set of types?
> Wouldn't it be simpler for application developers to make several
> requests for
> different types?
> Like requesting access to a local media storage service and then, if
> needed,
> requesting access to a print service.
> Wouldn't it be simpler as well for users to grant access for one
> service type
> at a time?

Well, that's still possible with what we have specified today. You could 
request one service type per call to getNetworkServices and you would 
have the experience you're after above.

Allowing multiple types in a single request allow us to do cool things 
with the UA prompt. For example, we will be showing devices in the UA 
prompt. If one device happens to support two requested service types, 
then the user need only select that device once.

It also means we can take both upnp: and a zeroconf: types in a single 
call to getNetworkServices and display a combined UA prompt with the 
devices that match either/or of those requested types. Whether those 
devices are UPnP or Zeroconf based is irrelevant in that scenario.

> Also, one NetworkServices for each service type may be more convenient.
> For instance, onserviceavailable handlers would directly be linked to
> a single
> service type.]]

Again, you could enforce this in your app by calling getNetworkServices 
once for each service type you want.

The fact is that a zeroconf and upnp service may be indistiguishable 
from a user's perspective if they provide similar services. The plumbing 
of interacting with those services may differ but that's a job for the 
application logic to abstract away from the user. Allowing authorization 
to happen in a single call and relying on the application to talk 
different dialects to each service is acceptable and a better user 
experience than having to request each service individually.

> 2. Questions about available services. From Youenn [7]:
> [[What is the goal behind servicesAvailable?
> What functionality does it bring to web applications?
> Wouldn't the current NetworkServices events and authorized services
> length be
> sufficient in most cases?
> Or just as a boolean value stating that there are some changes in the
> services
> of interest?
> It seems that serviceAvailable is counting services of potentially
> different
> types, which may not be all that useful.]]

It will notify you if the number of services available of a type equal 
to any of the original requested service types changes in the network. 
It's intended as a flag that will allow your web application to respond 
to perceived changes in the current network, if it so wishes to do so 
(instead of, for example, polling getNetworkServices every X seconds 
with a knock-on bad user experience).

If you're already requesting these services in the original call to 
getNetworkServices then you've already presumably implemented the 
application logic to handle these services. When servicesAvailable 
changes, you may like to re-issue a call to getNetworkServices, since 
there's a likelihood that more services may be added to the current set 
of services being provided to your web page.

> 3. Questions about service monitoring. From Youenn [7]:
> [[Service monitoring
> Monitoring of services availability looks like a useful feature.
> Probably a user has three options that should be clearly stated:
> - A user is granting permission to 1+ service(s) and grants permission to
> monitor services
> - A user is granting permission to monitor services
> - A user is denying permission to any service and to monitoring
> As per step 9 in section 4.1, it is not explicit whether the second
> option is
> valid.
> Two choices are currently described: granting permission to 1+
> services or
> denying permission (probably to all services?).

The spec says the following:

"The NetworkServices interface represents a collection of zero or more 
indexed properties that are each a user-authorized NetworkService object."

If the user provides zero services, then you have the second option 
above. I'm not sure how the dialog would handle that case but it's 
certainly made possible by the specification as it is written now.

> Also, what about a user that wants to grant access to one specific
> service
> while denying access to monitoring information?
> Maybe this behavior does not make any sense in practice?

We'd need a use case where this does make sense. Do you have one?

> But the spec could probably be updated to enable that behavior at a small
> cost.
> Something like not mandating to add the generated NetworkServices in
> the list
> of active service managers.
> Or making the serviceavailable/serviceunavailable events sending
> optional?]]

Such a change would need to be based on a common use case.

> 4. Relationship with Web Intent based discovery. From Youenn [7]:
> [[Service monitoring is a potentially nice feature in the network
> discovery
> API specification.
> This monitoring does not seem to be available with the "Web Intents
> Addendum -
> Local Services" approach.
> For instance, dynamically adding a print button, or changing its
> color, when a
> local printer is showing up may be convenient in terms of user
> experience.
> This seems to be feasible with this API, while this may not be the
> case with
> the web intents approach.
> Is that ok as is?
> Is monitoring out of scope (or a potential requirement) for the "Web
> Intents
> Addendum - Local Services" approach?
> Should service monitoring be a separate feature that can be used by both
> approaches?

This should be addressed in that line of work I think (Web Intents). 
Anything we need to do here related to the NSD spec? If we end up 
deciding on sharing a mechanism for that then we could come back to this 
in the NSD spec work?

> More generally, the question of the relationship between the two
> approaches
> will probably show up in the future (what is the difference, what is the
> scope, which approach should I use...).
> It may be good to have some answers publicly available (if it is not
> already
> the case?).]]

Essentially, the Web Intents Addendum Local Services was about 
specifying a new UPnP and Zeroconf Service Type specifically for 
handling Web Intents. You would not be able to use it to connect with 
e.g. any of the UPnP services specified on unless that device 
was patched with the Web Intents UPnP service also.

The NSD spec is about communicating with any UPnP Service Type - 
existing or new (including but not limited to those provided on, without requiring any hardware or software changes to 
existing or new UPnP-based devices. The same priniciple applies to 
Zeroconf-based devices and services via this API.

Perhaps others have observed additional differences between the two 
approaches. They do not share all that much in common IMO other than the 
discovery protocols being used at their root.

> 5. Questions on whitelist removal. From Youenn [8]:
> [[To disable access to a particular service, a user can decide to remove
> access to all services (reloading the app or recalling the function
> using the
> web app UI).
> Some browser implementations may want to propose authorization removal
> globally or on a per service basis.

Whitelisting in the specification is really a small extension to CORS. 
Actually its something that's been dubbed 'reverse CORS' where the user 
grants cross-origin permission via service opt-in themselves (instead of 
that permission coming implicitly from the service itself). If your 
request makes sense in the scope of CORS then it may make sense here too.

> Is it the purpose of the "ongoing local-network communication" indicator?
> In that case, if a user disables access to a particular service, how
> would the
> application be notified of such change?

A 'serviceoffline' event is fired on the affected NetworkService object 
and its online attribute would simultaneously be set to false.

> Is it expected that the application will be notified from error messages
> coming from the protocol level?

No. We have deliberately obfuscated errors for both privacy and 
simplicity. The web page only really needs to know if access was granted 
or not. The cause of any error is not something that needs to bubble up 
to the web application - unless there are any use cases in which that is 
essential and warrant us having a further look at this.

> What happens if there is an ongoing XHR exchange?]]

HTTP provides all the handling for this case. We have the 4XX range and 
timeouts available if the service is knocked offline during an ongoing 
XHR exchange.

> 6. No access to previous services. From Youenn [7]:
> [[The four bullets at the end of section 4.1 describe when access to
> any of
> the whitelist URL is authorized or not.
> After reading the different points, everything is not crystal clear to
> me.
> Here are some questions that came to my mind:
> What is the exact meaning of the first bullet (same script related in
> same or
> different window)?

It means if you reload the page or open a new page that includes the 
same script you don't automatically get access to the same 
NetworkServices that you may have been granted in the previous page. A 
call to getNetworkServices is stateless (it does not persist across 
sessions or domains).

> What potential security issue is it addressing?

Persistence of NetworkService sharing is addressed by the user agent. 
For example, if the user clicks a 'Remember my sharing preferences for 
this domain' button, we could automatically invoke the successCallback 
of the getNetworkServices call with the previous NetworkServices object.

What this bullet-point says is that this does not happen automatically 
and cannot be set by the script itself.

> Does it mean that if the same script is loaded in two different windows,
> the authorizations for the script in the first window are cancelled
> (whitelist
> becomes empty) when the script in the second window is loaded?

No. The second script and its corresponding permissions act 
independently of the first script.

> If that is the case, similarly to the previous point 5 on whitelist
> removal,
> while it is easy for application developers to understand that
> authorizations
> are removed when getNetworkServices is called again,
> it may be less obvious for developers to handle bullet 1.

Developers should be aware that a call to getNetworkServices is 
stateless, much like Geolocation or getUserMedia calls.

> As of the second bullet, does it mean that all granted URLs are
> removed from
> the whitelist when getNetworkServices is called again?

If you re-invoke getNetworkServices then you will get a new opt-in 
dialog. That opt-in dialog would include the current list of services 
shared with the current page pre-highlighted in the list of all devices 
currently available on the network and matching the requested service 
types in the getNetworkServices call. This dialog would require the user 
to remove one of these highlighted services for the situation you 
describe here to occur. That's a perfectly reasonable use case IMO but 
it means the other services that were pre-highlighted and re-shared with 
the page would remain unaffected (in reality all previously shared 
services actually all get removed and then re-added immediately 
according to the getNetworkServices algorithm).

> If so, would it make sense to exactly precise when the previous
> whitelist is
> emptied?
> Section 4.1 defines the different steps of the getNetworkServices call
> and one
> could envision doing this at step 1, 12 or 18 for instance.

Yes, this is a good idea. I've updated the spec accordingly (now Step 12 
in the getNetworkServices algorithm defined in Section 4.1):

> If a web application has access to a content provider and also wants
> to access
> a particular printer, the app will call again getNetworkServices.
> It would be nice if the access to the content provider is not cut
> during the
> 10 seconds the user takes to answer to the getNetworkServices call.

I believe the commit above addresses this, considering the removal and 
addition of whitelisted items to the URL whitelist is done 
instantaneously after the user has already clicked 'OK' on their 
authorization dialog.

Before the user clicks 'OK' the old URL whitelist would still be in effect.

> The third bullet (going through the history) probably leads to empty the
> current whitelist.
> On the other hand, the fourth bullet (a script running in a different
> origin)
> does not probably lead to empty the current whitelist.
> This fourth bullet may different in nature to the other items and, if
> that is
> the case, may be separated from the list.]]

The fourth bullet does not empty the current whitelist for the current 
origin. Only when the user navigates away from the original page will 
the URL whitelist for that origin be affected. I'm not sure why we would 
want to separate this from this list. More discussion may be helpful.

> 7. Active service managers. From Youenn [7]:
> [[The list of active service managers contains the NetworkServices
> objects
> being shared with all web pages.
> Each NetworkServices object in that list will issue serviceavailable
> events
> whenever needed.
> NetworkServices objects not in this list will not generate those events.


> What happens to a NetworkServices object delivered by a
> getNetworkServices
> call that is made obsolete by a new getNetworkServices call?

The old NetworkServices object is still present in the 'list of active 
service managers'. At no point does this object get removed from the 
list in the specification. Therefore, any event changes will also be 
applied to old NetworkServices objects whether they are still active or not.

> Is it still in that list of active service managers?


> When reading section 9, it seems to be the case.
> But what is the point in processing online/offline events for services
> that
> the application can no longer get access to?

A NetworkServices object provided to a web page is immutable. Because it 
cannot be changed and cannot be revoked by the user agent once provided 
to a script that NetworkServices object will exist until the user 
navigates away from the current page.

If the page is still using this object then we still treat it as an 
active object in the page and fire all necessary events on that object 
as usual.

> Would it make sense to apply section 4.1 rules on NetworkServices object
> removal from the list of active service managers?

Unfortunately, we cannot remove active JavaScript objects once they have 
been shared with the current web page. This can only happen once the 
user navigates away from that page or reloads that page (and hence the 
state of the JS in the page is lost and the NetworkServices object can 
no longer exist until re-supplied by the user agent).

> Also, if a user is revoking access authorizations, he may also want to
> revoke
> the implicit monitoring authorization.]]

The NetworkServices object does not have special behaviour applied to it 
if or when it is superseeded by a second call to getNetworkServices and 
a second NetworkServices object has been returned. Both of these objects 
are still NetworkServices objects and therefore act in a consistent way.


Anyone still reading this far? ;)

- Rich

> [0] - Latest WD
> [1]
> - from Greg
> [2]
> - Rich's response to [1]
> [3]
> - Greg's follow-up on [2]
> [4]
> - from Cathy
> [5]
> - Rich's response to [4]
> [6]
> - Cathy's follow-up on [5]
> [7]
> - from Youenn
> [8]
> - Cathy's follow-up on previous comments by JCD
> [9]
> - JCD's follow-up on [8]
> [10]
> - Cathy's follow-up on [9]
> [11]
> - from Naoyuki Sato
> [12]
> - JCD's follow-up on [11]
> [13]
> - Naoyuki Sato's follow-up on [12]
> [14]
> - Cathy's follow-up on [13]

Received on Tuesday, 5 February 2013 14:36:27 UTC