diff --git a/index.html b/index.html index 019ef64..e80328d 100644 --- a/index.html +++ b/index.html @@ -23,6 +23,11 @@ name: "Matt Giuca", company: "Google Inc.", companyURL: "https://google.com" + }, + { + name: "Eric Willigers", + company: "Google Inc.", + companyURL: "https://google.com" }], otherLinks: [{ key: "Implementation status", @@ -93,22 +98,30 @@

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

-
+
 {
   "name": "Includinator",
   "share_target": {
-    "url_template": "share.html?title={title}&text={text}&url={url}"
+    "action": "share.html",
+    "params": {
+      "title": "name",
+      "text": "description",
+      "url": "link"
+    }
   }
 }
 

- The url_template contains a number - of placeholder fields that will be replaced with the shared data when - the target is invoked. Placeholders are only replaced in the - query and fragment parts of the URL template. - Once the fields are replaced, it should be a URL that is relative to - the directory containing the manifest URL. + The params keys correspond to the key + names in ShareData from + [[!WebShare]], while the values are arbitrary names that will be used as + query parameters when the target is launched. +

+

+ When a share takes place, if the user selects this share target, the + user agent opens a new browsing context at the action URL, + with query parameter values containing the shared data, just like an + HTML form submission.

For the purpose of this example, we assume the manifest is located at @@ -123,25 +136,21 @@

<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')); + console.log('Title shared: ' + parsedUrl.searchParams.get('name')); + console.log('Text shared: ' + parsedUrl.searchParams.get('description')); + console.log('URL shared: ' + parsedUrl.searchParams.get('link')); }); </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 + 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
+
+https://example.org/includinator/share.html?name=My%20News&description=&link=http%3A%2F%2Fexample.com%2Fnews
 

How the handler deals with the shared data is at the handler's @@ -176,8 +185,16 @@

"!appmanifest#dom-webappmanifest">WebAppManifest dictionary.

+dictionary ShareTargetParams {
+  USVString title;
+  USVString text;
+  USVString url;
+};
+
 dictionary ShareTarget {
-  required USVString url_template;
+  required USVString action;
+  DOMString method = "GET";
+  required ShareTargetParams params;
 };
 
 partial dictionary WebAppManifest {
@@ -229,65 +246,36 @@ 

  • If share target is undefined, then return undefined.
  • -
  • Let URL template string be share - target["url_template"]. -
  • -
  • If URL template string is undefined, +
  • If share + target["method"] is not an + ASCII case-insensitive + match for the string "GET", issue a - developer warning that url_template is required, and return + developer warning that the method is not supported, and return undefined.
  • -
  • Let URL template be the result of running the - URL parser on URL - template string, with manifest URL as the - base, and no encoding override. - (Validation errors are - expected due to { and }, and should be - ignored.) If the result is failure, issue a developer - warning that url_template is - invalid, and return undefined. +
  • Let action be the result of + parsing the + URL share + target["action"], relative to + the manifest URL and with no encoding override. If the + result is failure, + issue + a developer warning and return undefined.
  • -
  • If URL template is not If action is not within scope of scope URL, - issue a developer warning that url_template is outside of the navigation scope, and - return undefined. -
  • -
  • If URL template's query is not null, run the replace - placeholders algorithm on URL template's query with - {} (the empty ShareData). If the result - is failure, issue a developer - warning that url_template is - invalid, and return undefined. -
  • -
  • If URL template's fragment is not null, run the - replace placeholders algorithm on URL template's - fragment with {}. If the result is failure, - issue a - developer warning that url_template is invalid, and return - undefined. -
  • -
  • Set share target["url_template"] to URL template. + issue a developer warning that + action is outside of the + navigation scope + , and return undefined.
  • +
  • Set share target["action"] to action.
  • Return share target.
  • -

    - The above steps that run the replace placeholders algorithm - are to validate the URL template and throw away the result. If it is - invalid, the share target is ignored. The launch algorithm below - repeats these same steps using the actual share data. -

    @@ -297,31 +285,44 @@

    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. + The action member specifies the URL for the + web share target. +

    +

    + The method member specifies the HTTP request + method for + the web share target. +

    +

    + The params member contains a ShareTargetParams + dictionary. +

    +

    + ShareTargetParams and its members +

    +

    + The ShareTargetParams dictionary contains the following + members. +

    +

    + The title member specifies the name of the query parameter + used for the arbitrary text that forms the body of the message being + shared. +

    +

    + The text member specifies the name of the query parameter + used for the title of the document being shared.

    -
    - The characters U+007B ({) and U+007D (}) - are invalid in a valid URL - string (although they parse without being percent-encoded, they - trigger a validation error). Thus, they unambiguously represent - placeholders in the url_template string. Literal curly bracket - characters can be represented via percent-encoding, as - %7B and %7D. -

    - 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. + The url member specifies the name of the query parameter + used for the URL string referring to a resource being shared. +

    +

    + The query parameters will be populated with information from the + ShareData + being shared. If the ShareData contains no information for a given + member, the query parameter will receive an empty string.

    @@ -447,139 +448,61 @@

    run the following steps:

      -
    1. Let URL template be - manifest["share_target"]["url_template"]. Assert: URL template is not - undefined. +
    2. + Let action be manifest["share_target"]["action"].
    3. -
    4. Let final URL be a copy of URL template, - with the following changes: -
        -
      1. If URL template's query is not null, final - URL's query is the result of running the replace - placeholders algorithm on URL template's query - with data. Assert: This did not return failure. -
      2. -
      3. If URL template's fragment is not null, final - URL's fragment is the result of running the replace - placeholders algorithm on URL template's fragment - with data. Assert: This did not return failure. -
      4. -
      +
    5. + Let entry list be a new empty list of name-value tuples.
    6. -
    7. Run the window open - steps on final URL, with empty target and - empty features. -
    8. -
    -

    - The assertions in this algorithm assume that manifest has - had the post-processing the share_target member - algorithm run on it and still has a share_target afterwards. - That algorithm deletes any share_target member that would - violate these assertions. -

    -
    -

    - Only the query and fragment parts of the URL have placeholders - replaced. Placeholders cannot be replaced in the path, because - otherwise it would allow a path escape. For example, a template of - "app/create/%(text)" would allow the sharer to supply - a text of "..", resulting in a final URL of - "app". -

    -
    -

    - 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. + For each member in the sequence « "title", + "text", "url" », +
          +
        • + Let name be the value of + manifest["share_target"]["params"][member].
        • -
        • Let start be the index of the first occurrence of - U+007B ({) in template. +
        • + If name is undefined or an empty string, + then continue.
        • -
        • Let end be the index of the first occurrence of - U+007D (}) in template. +
        • + Let value be the value of + data[member].
        • -
        • If end < start, return failure - (unmatched closing brace). +
        • + If value is undefined, set + value to an empty string.
        • -
        • Let key be the characters in template - in between indices start and end, - exclusive. +
        • + Append to entry + list a tuple with name and value.
        • -
        • If key is not a valid WebIDL identifier, return failure - (invalid key). -
        • -
        • Let value be data[key] (this - is always a USVString). - If it is undefined, let value be the empty string. -
        • -
        • Replace each character of value, c, - with the result of UTF-8 - percent encoding c using the reserved - percent-encode set. -
        • -
        • Replace the characters in template from indices - start to end, inclusive, with - value. -
        • -
      + +
    2. +
    3. + Let query be the result of running the + + application/x-www-form-urlencoded serializer with + entry list and no encoding override.
    4. -
    5. If template contains U+007D (}), return - failure (unmatched closing brace). +
    6. + Set action's + query + component to query.
    7. -
    8. Return template. +
    9. + Run the window open steps + on action, with empty target and empty + features.
    -
    -

    - 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. -

    -
    -

    - The reserved percent-encode set is the userinfo percent-encode set - and U+0024 ($), U+0025 (%), U+0026 (&), U+002B (+), and U+002C - (,). -

    - The reserved percent-encode set is the complement of the - "unreserved" set in [[rfc2396]], the same set used by encodeURIComponent - from [[ECMAScript]]. -

    -

    - The reserved percent-encode set should be defined in [[!URL]], - not here. See whatwg/url#369. + This algorithm assumes that manifest has + had the post-processing the share_target member + algorithm run on it and still has a share_target afterwards.

    @@ -622,6 +545,10 @@

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

    +

    + Thanks to Alex Russell and David Baron, for their feedback on early + drafts of this spec. +