w3ctag / design-reviews

W3C specs and API reviews
Creative Commons Zero v1.0 Universal
327 stars 55 forks source link

Web Share Target API #221

Closed mgiuca closed 6 years ago

mgiuca commented 6 years ago

Hello TAG!

I'm requesting a TAG review of:

Further details (optional):

You should also know that...

Questions for the review panel:

We'd prefer the TAG provide feedback as (please select one):

Thanks and feel free to post any follow-up discussion questions here.

owencm commented 6 years ago

FYI our intent to ship is only currently blocked on TAG review and we'd like to not bypass this step, so would really appreciate a review ASAP.

dbaron commented 6 years ago

So a few thoughts so far (in somewhat random order):

dbaron commented 6 years ago

Maybe a bigger issue here is thinking about what the path forward for better integration with both newer (mobile-focused) operating systems and older desktop-focused operating systems is. On desktop operating systems, there's often a mechanism for registration and handling of file MIME types, but registerContentHandler never took off. (On the other hand, registerProtocolHandler did, to match the parallel systems for protocol handling, which have sometimes been abused substantially to do things that aren't really protocols.) Is it the right mechanism, or as Anne suggests above, not? (Maybe it's right for native→web but doesn't work well for web→web?)

dbaron commented 6 years ago

Oh, and a final comment related to registries: it seems like there ought to be a master list somewhere of the extensions to WebAppManifest (and, for that matter, other uses of WebIDL partial) so that we don't end up with conflicting ones. (That's particularly interesting in this case given our discussion about preserving the ability for the origin policy and the web app manifest being the same file.) That's sort of the risk of partial... but eventually shouldn't these extensions get rolled back into the original spec so people can keep track of them?

plinss commented 6 years ago

There's also already a standard syntax for URL templates: https://tools.ietf.org/html/rfc6570 (with several npm module implementations) suggest we re-use that rather than reinventing the wheel there.

mgiuca commented 6 years ago

Hi David,

Thanks for the write-up. Sorry it's been awhile. I have been dealing with the URL escaping issue which is blocking the WST spec.

  • I'm slightly disturbed that WebAppManifest uses underscores in the names of the members of the dictionary... but this is at least consistent with that, which is better than being inconsistent. (I mean... I actually like underscores in general, but they haven't been popular in web APIs elsewhere.)

I think this is out of scope here (as you say, WST is consistent with the rest of the Manifest API). FWIW, this has caused some trouble already (we've talked about APIs that share the IDL dictionaries in the Manifest spec, and the issue came up that we would need to modify the IDL spec to automatically convert between underscore and camel-case because underscores would be unacceptable in JavaScript APIs). Well that never eventuated, but it is annoying. I think it's too late to not add underscores to Manifest members.

  • I've been wondering for a while about having something MIME-type specific, for example, to address things like the use case of calendar apps that want to receive text/calendar files (even those not coming from the Web Share API). See, for example, a recent discussion on mozilla.dev.platform about removal of navigator.registerContentHandler. That's perhaps broader than a general share/share target API, but I've thought it was something useful to solve. (Consider, for example, pages from those for WebEx conference calls to my dentist that offer ICS files (text/calendar) that I'd love to add to my google calendar from my browser.) It seems at least worth thinking about whether this API could be extended to handle that case, even if it doesn't happen right now.

Yes. I don't want this right now, but we need to make sure it can be extended into this. There's a proposal for Web Share to be able to share blobs. This has been a big feature request for WST also (mostly, receiving images). I think they would come in through the same mechanism; a Blob would be created in the document context containing the file, and then a new field would be added to the ShareData (and thus, come in as a URL parameter) referencing the Blob URL.

We can also filter by MIME type by adding new parameters to the share_target dictionary (which currently has just one field; it’s designed to be extended).

I think the existing WST proposal can be extended into this later.

  • a dummy parse using empty values (or nonempty alphabetic values) seems reasonable to me; I can't think of anything better offhand, though maybe @annevk has ideas

So @annevk and I have been talking on WICG/web-share-target#31 about parsing the template. It looks like we want to pre-parse the template at manifest parse time (resolving the relative URL before substituting template parameters), and that would address the above issue. The downside of this is it appears we need to change the syntax from "{text}" to "%(text)". I'm hesitant about this because of @plinss comment (I'll address below).

  • sites supporting this presumably need to be pretty careful even if the arbitrary data ends up in the query string. Limiting to being in the query string or the hash seems less than ideal, but allowing things like .. also seems less than great. (What are the rules on interpreting escaped /?) Imposing a particular URL structure seems less than ideal -- but on the other hand, you could think of it like form submission, which is where I suppose query strings came from in the first place. I suppose I can't make a particularly strong argument either way, but maybe others have thoughts.

The path is ... unfortunate, but it looks like we'll have to limit this to query and fragment only.

Processing a query string is pretty fool-proof. We will automatically escape '=' and '&' and any other reserved characters, so as long as the receiver processes the query by: 1. Splitting on '&', 2. Splitting those parameters on '=' to a key,value pair, 3. Decoding percent-escapes... then any arbitrary string can be handled correctly. As you say, this is the same as a form submission, so all web sites need to be able to handle this.

  • the spec probably should describe the escaping of data that implementations do when substituting into the placeholders in the url_template; it doesn't currently appear to describe this.

It does: see Step 1.7 of the replace placeholders algorithm: "Replace each character of value, c, with the result of UTF-8 percent encoding c using the userinfo percent-encode set."

However, I've recently discovered that this is wrong. The userinfo percent-encode set doesn't encode nearly enough characters (notably '&' and '+'). I've been looking into exactly how to define this properly for the past week in whatwg/url#369. It's complicated, but I basically want to define it as "the complement of the unreserved set from RFC 2896". (That is, the same algorithm as encodeURIComponent.) We're just figuring out how to write that out in web spec language (since we use URL Standard, not RFCs).

Maybe a bigger issue here is thinking about what the path forward for better integration with both newer (mobile-focused) operating systems and older desktop-focused operating systems is. On desktop operating systems, there's often a mechanism for registration and handling of file MIME types, but registerContentHandler never took off. (On the other hand, registerProtocolHandler did, to match the parallel systems for protocol handling, which have sometimes been abused substantially to do things that aren't really protocols.) Is it the right mechanism, or as Anne suggests above, not? (Maybe it's right for native→web but doesn't work well for web→web?)

It’s harder on a system without a native intent system. There are a couple of answers (unfortunately some of these overlap with one another):

Oh, and a final comment related to registries: it seems like there ought to be a master list somewhere of the extensions to WebAppManifest (and, for that matter, other uses of WebIDL partial) so that we don't end up with conflicting ones. (That's particularly interesting in this case given our discussion about preserving the ability for the origin policy and the web app manifest being the same file.) That's sort of the risk of partial... but eventually shouldn't these extensions get rolled back into the original spec so people can keep track of them?

I think we can avoid this by simply standardizing this into the Web App Manifest spec. At the moment, it makes sense for it to be its own separate spec, but if we do put this on a standards track, I would expect it to be merged into that spec, so we don’t need to keep track of a list of extensions.

@plinss: There's also already a standard syntax for URL templates: https://tools.ietf.org/html/rfc6570 (with several npm module implementations) suggest we re-use that rather than reinventing the wheel there.

Yikes! I wasn’t aware of this. It certainly looks relevant (just “Level 1” specifically). And coincidentally, it’s the exact syntax we settled on before the proposed syntax change in WICG/web-share-target#31. There’s just one problem: we reference the URL Standard, not RFC 3986, for our definition of a URL and URL processing. (This seems to be true of all new web standards.) I don’t see how to reconcile RFC 6570 with URL Standard.

Aside from URL Standard compatibility, there are a few other problems with this:

Still, this gives me renewed interest in keeping the “{text}” syntax instead of changing to ”%(text)”, for compatibility with RFC 6570. I will discuss on WICG/web-share-target#31.

slightlyoff commented 6 years ago

Discussing today with @plinss at the W3C TAG meeting in London.

One discussion point regarding RFC 6570 and the timing of resolution, it seems that perhaps one way out of this pickle would be to drop the URL-only version and double-down on the share event in the Service Worker. In that solution, it's possible to pack whatever arguments and payload you like as part of the body of a Request that you can pass along with the event. That model naturally allows you to do the URL validation at registration/install time and not runtime.

Is there a compelling reason to continue down the URL-only path, particularly given that many (I hope most!) Share Target implementations will happen via PWA installability (which already requires a SW)?

/cc @mgiuca

mgiuca commented 6 years ago

Yes, if we went with the Service Worker approach, we side-step the entire issue of URL template syntax, since it's coming in through a JavaScript object (essentially it would be a ShareData object from Web Share). Initially, we were considering these two approaches in parallel, but we stopped considering the Service Worker approach a long time ago, for a number of fairly compelling reasons:

  1. The URL template approach does not require a Service Worker at all. While it's a nice carrot to convince people to make a SW, it isn't really necessary, and this just slows adoption of WST.
  2. The URL template approach can be implemented into existing share services with a single line in the manifest, and no code changes. For example, we just emailed Twitter a single line to add to the manifest and the next day, it was there and Twitter was a working Web Share Target (because they already had an endpoint URL that receives a share in the query parameters). Integrating into a SW is a more significant engineering investment.
  3. While the SW allows you to do things like receive a share without opening a new window/tab, this is almost always something you want to do anyway.
  4. The URL template approach fits neatly into the Service Worker navigate event proposal which I made last year. Instead of adding a new event to SW for WST, we can do the same thing by catching a launch event with the WST data in a URL.

Basically, simplicity trumps flexibility. I'd rather stick with the URL approach.

Also (and this shouldn't be a particularly strong argument when considering a web standard, but I'll say it), we have working implementations on Chrome for both mobile and desktop, as well as websites like Twitter that have implemented it.

domenic commented 6 years ago

While the SW allows you to do things like receive a share without opening a new window/tab, this is almost always something you want to do anyway.

Services like Pocket seem like a notable counterexample here, based on my experience using Android's share functionality.

Is there a plan for such services in the web share target world?

mgiuca commented 6 years ago

Services like Pocket seem like a notable counterexample here, based on my experience using Android's share functionality.

Yes, the "save for later" style of sharing is the one use case we've identified for receiving a service worker event rather than opening a page. But it is a soft requirement. You certainly could show a tab that says "I've saved this for later [Close]." Or "Do you want to save this for later? [Save] [Cancel]".

Is there a plan for such services in the web share target world?

Yes, the Service Worker navigate event. (Edit: Full site with explainer and demo.)

plinss commented 6 years ago

David and Alex will attempt to meet with mgiuca to discuss further offline

mgiuca commented 6 years ago

Sounds good. Let me know a time and I'll try to make it. 9am to 6pm weekdays Sydney time are best (if you are in the USA, this means afternoon/evening Sunday to Thursday). (Can email my GitHub username at chromium.org.)

ewilligers commented 6 years ago

Summary of 2018-02-27 discussion with @mgiuca @ewilligers @slightlyoff @dbaron :

We should add non-normative text encouraging user agents to require a service worker, to create a reliable user experience.

Instead of template substitution into a URL, consider using GET/POST form submissions. The application's desired field names could be specified in the manifest. Binary blobs would only be permitted with POST submissions, and the manifest could specify the accepted MIME types. Applications can use Request.formData to read everything out of the POST easily. Syntax might resemble

 {
     "name": "Includinator",
     "share_target": {
         "action": "share.html",
         "method": "POST",
         // Keys are the official field names. Values are the parameter names in the target URL.
         "params": {"title": "mytitle", "text": "mytext", "url": "myurl", "file": ["thephoto", ["image/*", "video/*"]], "file": ["ics_file", "application/ics"]},
     }
 }

This requires more investigation. Does formData block until everything is read and create an in-memory copy of everything? How might streaming be supported? We need to review again after we have a sample application the shares a URL and a sample application that shares multiple images and videos.

mgiuca commented 6 years ago

Note: A concern was raised on WICG/web-share-target#38 that the new syntax would not allow composing fields into the same query parameter (with delimiters). For example, they wanted to do this (using the old syntax):

"url_template": "?title={title}&body={text}%0A%0A{url}"

The "body" parameter is supposed to be populated with both the text and URL, separated by 2 newlines. Under the new syntax proposed above, you cannot make a templated parameter, you can only assign each ShareData field to one query parameter.

This shouldn't strictly be necessary, if you are in control of both the manifest and the receiver endpoint, you can just have the receiver receive all the fields individually and concatenate them in JS or on the server side. However, part of the appeal of the URL based approach is that you can just add it to the manifest without having to change an existing share endpoint (which may be much easier to adopt if you don't have to modify the syntax of your share endpoint). Perhaps we should use a template syntax still, but per-parameter:

"params": {"title": "{title}", "body": "{text}%0A%0A{url}"}

Counter-argument: The new scheme is modelled off HTML form submission. HTML forms don't let you compose a string from a template, you just pass along the fields as query parameters.

slightlyoff commented 6 years ago

Hey all,

Per the conversation in February of moving to a forms-based model, we (the TAG) are hoping the group here can ping back to advise on when you'd next like to discuss the design. We're happy to be as involved as you'd like us to be.

Thanks!

mgiuca commented 6 years ago

I think @ewilligers has a demo ready (or soon to be ready). Eric, can you share that here?

I think the ball is still in our court; we have a good idea of what the new model will be but we need to present a succinct summary of it for the group to review.

ewilligers commented 6 years ago

A demo for sharing small HTML and CSS files is live with source.

The sharing code uses the traditional navigator.share() API, except that we add a "files" member to the dictionary. This contains a FileList (or any File sequence).

The target's manifest specifies that it would like a POST request, and specifies the field names and accepted MIME types:

{
  "name": "WebShareTargetDemo",
  "share_target": {
    "action": "share-target-destination.html",
    "method": "POST",
    "params": {
      "title": "received_title",
      "text": "received_text",
      "url": "received_url",
      "files": [
        {
          "name": "received_html_files",
          "accept": "text/html"
        },
        {
          "name": "received_css_files",
          "accept": "text/css"
        }
      ]
    }
  }
}

The form POST can be handled client-side (by a service worker) or server-side.

For the initial version of Web Share Target, we will omit support for file sharing or POST requests. A typical manifest would be

{
  "name": "WebShareTargetDemo",
  "share_target": {
    "action": "share-target-destination.html",
    "params": {
      "title": "received_title",
      "text": "received_text",
      "url": "received_url"
    }
  }
}
kenchris commented 6 years ago

OK, this looks much simpler and more flexible as well. It is also great that you can handle it service worker side or server side.

What are the next steps? Will you be updating the spec text?

sorenrehkopf commented 6 years ago

Hi everyone, I'm guessing this isn't quite the right forum for this question, but info / disucussion on this project has been a little hard to come by. I'm wondering what the current status of this project is in chrome canary. It seems like an earlier version (the one initially posted) was available in canary at some point, but is no longer available now? Is the revised version discussed above going to be available in canary again sometime soon? If there's somewhere else I should ask about this let me know and I will move my questions there.

mgiuca commented 6 years ago

@sorenrehkopf As far as I know, Chrome Canary still supports Web Share Target. If it isn't working, please report to https://crbug.com/new and give relevant details. If you have questions about the project at an API level, please post them on https://github.com/WICG/web-share-target/issues. The current status of the design is as @ewilligers posted above 12 days ago.

sorenrehkopf commented 6 years ago

Thanks! Will do.

ewilligers commented 6 years ago

Draft spec for Web Share API with files https://ewilligers.github.io/web-share/ (diff)

Draft spec for Web Share Target API with files https://ewilligers.github.io/web-share-target/

We are proposing to initially ship Web Share Target API without files - PR

torgo commented 6 years ago

We're going to discuss further on the 19th.

slightlyoff commented 6 years ago

Hey all,

We came back through this issue at today's call, and are excited to see the updated drafts! Was wondering if it might be possible to update the Explainer to demonstrate the new flow as the examples in the new drafts are rather sparse.

Thanks again for working with us to iterate on this design. We'll try to digest the new spec and provide feedback by next week.

Regards

dbaron commented 6 years ago

I took a look at the new version of Web Share Target and it seems to be what I was expecting after our previous discussion.

There are a few areas that could perhaps be better defined, such as:

I also took a brief look at the associated version of Web Share, which I don't think I'd looked at before. A few questions came to mind:

Also, looking at issues that cross both specs:

mgiuca commented 6 years ago

@ewilligers: I think it's best to not post uncommitted versions of the spec to personal GitHub pages, since the versioning can get confusing (it's unstable since at any time, it reflects an unknown revision of an unknown branch).

The latest pull request is WICG/web-share-target#40, with a preview here including the big red disclaimer that this is a preview. It has gone through several rounds of code review since the document @dbaron is talking about (including addressing several of the concerns you raised). But it doesn't include the files part. Eric, perhaps you could create PRs for the "files" versions of these specs and then link to the Preview page instead of to your GitHub?

Note that we aren't planning to roll file sharing into the first version of Web Share Target. We're just thinking about it so we have a good model to extend into. The initial version of WST will more or less look like the above preview.

It would probably be useful to say what a share consists of.

The new version addresses this.

The definitions of the app manifest structure contain a bunch of normative "MUST" requirements that seem to be normative requirements on developers.

The new version addresses this. Specifically, the "MUST" requirement on the "action" member has been removed, since it was effectively an informative note. (Processing steps elsewhere say exactly what happens in this case.) I agree, that "MUST" should be reserved for conformance requirements on the processor (the user agent), not the content (the document); there isn't anything that content "MUST" do; rather, the standard describes how the processor handles all inputs.

I was curious why the canShare function exists given that what it does seems to be rather trivial -- or if it's intended to be extended to something more interesting in the future, whether it should return a Promise.

This was added in Eric's (not yet committed) file sharing version, as a way of allowing for feature detection of the files feature. See a long discussion on heycam/webidl#107. Without it, you wouldn't be able to know whether you're going to be able to share a file without actually trying it. This is a very rough sketch at this stage. It probably should return a Promise.

I'm a little curious about the use of FileList given that the type's definition says that it's "at risk". Does that statement of being "at risk" need to be revisited?

This is something we're actively talking about with the Chrome storage team who are trying to build on those file specs, and considering whether to try to resuscitate them or build something new.

In summary, let's not get too caught up on the file sharing details of Eric's private branch. We are not launching those features any time soon (in Chrome) and do not plan to land them in the spec soon either. We just want to make sure there is a reasonable model to expand into file sharing territory later.

We want the TAG review to focus on the title/text/URL share target which is currently in preview but will hopefully soon land in the WICG draft.

slightlyoff commented 6 years ago

This was discussed a bit today and @dbaron will look more closely at the version you just posted in the last comment, @mgiuca. That said, I'm confused about the use of GET vs POST in this draft. Perhaps I'm reading it wrong, but it appears that the only form encoding allowed is application/x-www-form-urlencoded, which precluded sending files. Further, as these request may mutate state at the dispatch site, should they not be sent as POSTs?

ewilligers commented 6 years ago

We are proposing to initially ship only the title/text/URL share target, without files.

Further, as these request may mutate state at the dispatch site, should they not be sent as POSTs?

I hadn't considered this. The proposal was to exclusively support GET requests for the initial version without files, using encoding consistent with <form method="GET">: Mutate action URL.

The intention for POST would be to use multipart/form-data only, like FormData (MDN). Sharing files would only be supported with POST.

mgiuca commented 6 years ago

@slightlyoff This raises a really good point. We've been thinking about POST as being the vehicle through which we deliver form data, so our plan was to only allow GET in the base version, but later add file sharing using POST. What I realised after reading your message is that POST isn't just a way of delivering large binary files; it also has different semantics (state mutating & non-repeatable).

I don't think we should mandate POST or make it the default, since many web share targets will not mutate state without further input from the user (e.g. https://twitter.com/intent/tweet?text=I%20use%20Web%20Share); refreshing these pages is fine and they are designed to be navigated with a GET request. The original point of using this URL-based design is to hook into those existing share mechanisms.

However, I now think we should support POST in the base standard for WST (so sites can reliably assume any user agent that supports WST also supports "method": "POST"). Even if you don't receive files, you can still use "method": "POST" if your site immediately mutates state without asking the user to confirm, and we should encourage sites to use the semantically appropriate method.

travisleithead commented 6 years ago

Note: need to checkout the correct draft: http://wicg.github.io/web-share-target

dbaron commented 6 years ago

OK, I had a look at the correct version this time. I filed three pull requests (see above), and also have a few comments:

It seems like it might be worth a non-normative note explaining future expansion plans for images/files (and their being POST-only) if that part of the spec isn't going to be written soon, just so it doesn't get forgotten and so somebody else could pick it up later.

Two of the comments in https://github.com/w3ctag/design-reviews/issues/221#issuecomment-400143812 still seem to apply:

  • It would probably be useful to say what a share consists of. I understand it to be a sort of arbitrary bundle of title, text, url, and in the future files. Right now that's stated in the example section but the relevant normative part of the spec seems to assume the reader knows what "the title", "the text", etc., are.

and (for both specs):

  • I wonder if there should be some way for associating MIME types with the files.

Otherwise things look good to me, at least after one read-through.

mgiuca commented 6 years ago

It seems like it might be worth a non-normative note explaining future expansion plans for images/files (and their being POST-only) if that part of the spec isn't going to be written soon, just so it doesn't get forgotten and so somebody else could pick it up later.

I agree — we could have a section similar to my Extensibility of this API section in Web Share, but I got some negative feedback on this in WICG/web-share#61.

It would probably be useful to say what a share consists of. I understand it to be a sort of arbitrary bundle of title, text, url, and in the future files. Right now that's stated in the example section but the relevant normative part of the spec seems to assume the reader knows what "the title", "the text", etc., are.

Aren't the descriptions in ShareTargetParams and its members enough?

I wonder if there should be some way for associating MIME types with the files.

I think that will be relevant when we introduce file sharing, but not for the initial version of the spec which doesn't include file sharing.

dbaron commented 6 years ago

It would probably be useful to say what a share consists of. I understand it to be a sort of arbitrary bundle of title, text, url, and in the future files. Right now that's stated in the example section but the relevant normative part of the spec seems to assume the reader knows what "the title", "the text", etc., are.

Aren't the descriptions in ShareTargetParams and its members enough?

I think not quite -- since they give me the feeling that I'm missing some description elsewhere. I think it's useful to state that it's basically an arbitrary set of data possibly coming from an OS sharing system or possibly coming from Web Share.

slightlyoff commented 6 years ago

Hey all,

Discussed at today's F2F; we're excited by the direction this spec is taking, so are closing this issue and looking forward to hearing from y'all if/when there are other issues that arise that we can advise on.

As a parting note, it would be great to see expanded examples, particularly ones that demonstrate how to deal with files and the POST mechanism from Service Workers. These don't seem to be in either the spec or explainer yet.

Thanks again for working with us!

mgiuca commented 6 years ago

Thanks @slightlyoff and @dbaron! I'm filing issues about these things you raised:

torgo commented 5 years ago

Hi @mgiuca just following this up. I noticed this behaviour working in WebAPK based webapps recently. However it doesn't look like this has percolated back into the webapp manifest specification. Is there a plan to bring this back to the webapp manifest spec itself?