Web Share Target API

Draft Community Group Report

Latest editor's draft:
https://wicg.github.io/web-share-target/
Editor:
Matt Giuca, Google Inc.
Participate:
GitHub WICG/web-share-target
File a bug
Commit history
Implementation status:
Chromium

Abstract

This specification defines an API that allows websites to declare themselves as web share targets, which can receive shared content from either the Web Share API, or system events (e.g., shares from native apps).

This is a similar mechanism to navigator.registerProtocolHandler, in that it works by registering the website with the user agent, to later be invoked from another site or native application via the user agent (possibly at the discretion of the user). The difference is that registerProtocolHandler registers the handler via a programmatic API, whereas a Web Share Target is is declared in the Web App Manifest, to be registered at a time of the user agent or user's choosing.

Status of This Document

This is a preview

Do not attempt to implement this version of the specification. Do not reference this version as authoritative in any way. Instead, see https://wicg.github.io/web-share-target/ for the Editor's draft.

This specification was published by the Web Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

This is an early draft of the Web Share Target spec.

1. Prerequisites

In order to implement this API, it is REQUIRED that the user agent implements Web App Manifest. This spec also re-uses some definitions from the Web Share API spec. Implementation of that spec is NOT REQUIRED to implement this one (but it is RECOMMENDED).

2. Usage Example

This section is non-normative.

To register a site as a share target, a share_target entry is added to the Web App Manifest, as shown:

Example 1: manifest.webmanifest
{
  "name": "Includinator",
  "share_target": {
    "url_template": "share.html?title={title}&text={text}&url={url}"
  }
}

The url_template contains a number of placeholder fields that will be replaced with the shared data when the target is invoked. Once the fields are replaced, it should be a URL that is relative to the directory containing the manifest URL.

For the purpose of this example, we assume the manifest is located at https://example.org/includinator/manifest.webmanifest.

Example 2: share.html
<html>
  <head>
    <link rel="manifest" href="manifest.webmanifest">
  </head>
  <body>
    <script>
      window.addEventListener('load', () => {
        var parsedUrl = new URL(window.location.toString());
        console.log('Title shared: ' + parsedUrl.searchParams.get('title'));
        console.log('Text shared: ' + parsedUrl.searchParams.get('text'));
        console.log('URL shared: ' + parsedUrl.searchParams.get('url'));
      });
    </script>
  </body>
</html>

When a share takes place, if the user selects this app as the share target, the user agent populates the fields of the URL template, then opens a new browsing context at that URL. Any missing fields are left empty (but note that the query parameters are not removed). For example, if an incoming share contains the title "My News" and the URL http://example.com/news, the user agent will open a new window or tab and navigate to:

https://example.org/includinator/share.html?title=My%20News&text=&url=http%3A%2F%2Fexample.com%2Fnews

How the handler deals with the shared data is at the handler's discretion, and will generally depend on the type of app. Here are some suggestions:

3. Extension to the Web App Manifest

The following IDL extends the WebAppManifest dictionary.

dictionary ShareTarget {
    required USVString url_template;
};

partial dictionary WebAppManifest {
    ShareTarget share_target;
};

The following steps are added to the extension point in the steps for processing a manifest:

  1. Set manifest["share_target"] to the result of running post-processing the share_target member given manifest["share_target"], manifest["scope"], and manifest URL.
Issue
The extension point actually needs to come after the other fields are post-processed. Otherwise, we will be using a potentially invalid or relative scope URL.

3.1 share_target member

The share_target member of the manifest is a ShareTarget dictionary that declares this application to be a web share target, and describes how the application receives share data.

A web share target is a web site in a secure context with a valid manifest containing a share_target member. A web share target is a type of share target.

Issue 27: Properly define the secure context requirement

A web share target is defined as "a web site in a secure context".

We need to more precisely define this requirement. Note that the secure context algorithm is defined over an environment settings object, not a URL. We need to block share targets that are specified from a non-secure manifest OR those final URL is non-secure.

The steps for post-processing the share_target member is given by the following algorithm. The algorithm takes a ShareTarget share target, a URL scope URL, and a URL manifest URL. This algorithm returns a ShareTarget or undefined.

  1. If share target is undefined, then return undefined.
  2. Let URL template be share target["url_template"].
  3. If URL template is undefined, then return undefined.
  4. Let test relative URL be the result of running the replace placeholders algorithm on URL template with {} (the empty ShareData). If the result is failure, issue a developer warning that the URL template is invalid, and return undefined.
  5. Let test absolute URL be the result of running the URL parser on test relative URL, with manifest URL as the base, and no encoding override. If test absolute URL is failure, issue a developer warning that the URL template is invalid, and return undefined.
  6. If test absolute URL is not within scope of scope URL, issue a developer warning that the URL template is outside of the manifest scope, and return undefined.
  7. Return share target.
Note

Unlike the other post-processing steps for URL members of the manifest, this algorithm does not update the manifest object with the absolute URL for url_template. This is because the URL parser won't work on the URL template; it can only be run after the placeholders are replaced at launch time.

Therefore, the above steps just validate the URL template, and if it is invalid, ignore the share target. The launch algorithm below repeats these same steps using the actual share data.

3.2 ShareTarget and its members

The ShareTarget dictionary contains the following members.

The url_template member describes which share data fields are passed to the web share target, and in what format. It contains zero or more placeholders of the form "{field}". Each field MUST be a valid WebIDL identifier, and SHOULD be a key of the ShareData dictionary. After these placeholders are removed, it MUST form a valid URL string.

Note
The { and } characters are illegal in a valid URL string, so they always represent a placeholder in the url_template string, and do not need to be escaped.

Any fields that are not present in the url_template will be silently dropped from the share payload when sharing to this app. The url_template MAY contain fields that are not ShareData keys, for forwards compatibility.

4. Registration of web share targets

How and when web share targets are "registered" is at the discretion of the user agent and/or the end user. In fact, "registration" is a user-agent-specific concept that is not formally defined here; user agents are NOT REQUIRED to "register" web share targets at all; they are only REQUIRED to provide some mechanism to convey shared data to a web share target of the end user's choosing. User agents MAY consider a web share target "registered" even if it is not installed.

The user agent MAY automatically register all web share targets as the user visits the site, but it is RECOMMENDED that more discretion is applied, to avoid overwhelming the user with the choice of a large number of targets.

Note

Examples of registration strategies that user agents can employ are:

  • Only register a web share target once it is installed.
  • Only register a web share target once the end user has used the site for some period of time.
  • Explicitly prompt the user to register a web share target (perhaps using the same UI as navigator.registerProtocolHandler).

When presenting the end user with a list of web share targets, the user agent MAY use an online service which has pre-indexed manifests, and therefore show the user targets that they have never visited or explicitly registered.

Issue 26: Way to explicitly register share targets

We may wish to provide a method for websites to explicitly request to prompt the user for handler registration. This would be limited to prompting to register the share_target already declared in the manifest (not dynamically creating share targets). For now, we have omitted such a method from the design to keep control in the hands of user agents. It is easier to add such a method later than remove it.

5. Handling incoming shares

A web share target is invoked when the end user is sharing some data intended for a generic application, and indicates that specific web share target as the receiver of the data.

It is not specified where the data comes from, or how the end user indicates the web share target as the receiver. However, one possible source is a call to navigator.share in the same user agent.

Note

Examples of other possible sources of a web share target invocation are:

  • From the built-in UI of the user agent (e.g., the end user picks "Share" from a browser's menu, to share the current page title as "title" and the current page URL as "url").
  • A share action triggered from a native application (via a proprietary share system), followed by the end user choosing a web share target as the receiver.

5.1 Obtaining a ShareData

When a web share target is invoked, the data MAY be in an unspecified format. The user agent MUST first convert the data into a ShareData dictionary, if it is not already, by mapping to the fields of ShareData from equivalent concepts in the host system. If the source was a call to navigator.share, the user agent SHOULD use the ShareData argument unmodified (but this is not always possible, as it might have to round-trip through some other format in a lossy manner). The user agent MAY employ heuristics to map the data onto the ShareData fields as well as possible.

Note

For example, the host share system may not have a dedicated URL field, but a convention that both plain text and URLs are sometimes transmitted in a "text" field. This is the case on Android. The user agent can check whether all or part of the "text" field is a valid URL string, and if so, move that part of the "text" field to the ShareData's url field.

5.2 Launching the web share target

When web share target having WebAppManifest manifest at URL manifest URL is invoked with ShareData data, run the following steps:

  1. Let relative URL be the result of running the replace placeholders algorithm on manifest["share_target"]["url_template"] with data. If the result is failure, abort these steps.
  2. Let final URL be the result of running the URL parser on relative URL, with manifest URL as the base, and no encoding override.
  3. If final URL is failure, abort these steps.
  4. If final URL is not within scope of manifest's scope URL, abort these steps.
  5. Run the window open steps on final URL, with empty target and empty features.
Note

This algorithm never aborts if manifest has had the post-processing the share_target member algorithm run on it. That algorithm deletes any share_target member that would fail these checks.

The replace placeholders algorithm takes a USVString template and ShareData data, and returns either a USVString or failure:

  1. While template contains U+007B ({):
    1. If template does not contain U+007D (}), return failure (unmatched opening brace).
    2. Let start be the index of the first occurrence of U+007B ({) in template.
    3. Let end be the index of the first occurrence of U+007D (}) in template.
    4. If end < start, return failure (unmatched closing brace).
    5. Let key be the characters in template in between indices start and end, exclusive.
    6. Let value be data[key] (this is always a USVString). If it is undefined, let value be the empty string.
    7. Replace each character of value, c, with the result of UTF-8 percent encoding c using the userinfo percent-encode set.
    8. Replace the characters in template from indices start to end, inclusive, with value.
  2. If template contains U+007D (}), return failure (unmatched closing brace).
  3. Return template.
Note

The above algorithm assumes that all values of ShareData are of type USVString, which is currently the case. If new members are added in the future that are not strings, the above algorithm will need to specify conversion to a string.

For example, if an image member is added, this would likely be an ImageBitmapSource, which would be converted into a Blob URL before being inserted into the URL template.

6. Security and privacy considerations

This section is non-normative.

A. Acknowledgments

This section is non-normative.

Thanks to the Web Intents team, who laid the groundwork for the web app interoperability use cases. In particular, Paul Kinlan, who did a lot of early advocacy for Web Share and Web Share Target.

Thanks to Connie Pyromallis, who wrote an early draft of this spec, and helped design and prototype the API.

B. References

B.1 Normative references

[appmanifest]
Web App Manifest. Marcos Caceres; Kenneth Christiansen; Mounir Lamouri; Anssi Kostiainen; Rob Dolin. W3C. 29 November 2017. W3C Working Draft. URL: https://www.w3.org/TR/appmanifest/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[SECURE-CONTEXTS]
Secure Contexts. Mike West. W3C. 15 September 2016. W3C Candidate Recommendation. URL: https://www.w3.org/TR/secure-contexts/
[URL]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL]
Web IDL. Cameron McCormack; Boris Zbarsky; Tobie Langel. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/
[WebShare]
Web Share API. Matt Giuca. WICG. Draft Report. URL: https://wicg.github.io/web-share

B.2 Informative references

[FileAPI]
File API. Marijn Kruisselbrink. W3C. 26 October 2017. W3C Working Draft. URL: https://www.w3.org/TR/FileAPI/
[web-intents]
Web Intents. Greg Billock; James Hawkins; Paul Kinlan. W3C. 23 May 2013. W3C Note. URL: https://www.w3.org/TR/web-intents/