├── .pr-preview.json ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── demos ├── images │ ├── README.md │ ├── favicon.ico │ ├── icon-128.png │ ├── icon-16.png │ ├── icon-180.png │ ├── icon-256.png │ ├── icon-32.png │ ├── icon-48.png │ └── icon-512.png ├── index.html ├── manifest.json ├── sharetarget.html └── sw.js ├── docs ├── explainer.md ├── interface.md ├── mocks │ ├── README.md │ ├── share_mobile_handler.png │ └── share_mobile_web_web.png └── native.md ├── index.html ├── level-2 └── index.html ├── tidyconfig.txt └── w3c.json /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "level-2/index.html", 3 | "type": "respec" 4 | } 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Everyone is welcome to contribute to this specification. 4 | 5 | Any simple editorial contribution can simply be done with a GitHub Pull Request. 6 | You can even do an inline edit of the file on GitHub. 7 | 8 | For more substantial contributions, please first start a thread in the 9 | [webapps mailing list](https://lists.w3.org/Archives/Public/public-webapps/) at the W3C. 10 | 11 | Note: Contributions to this repository are intended to become part of Recommendation-track documents governed by the 12 | [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy-20040205/) and 13 | [Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). To make substantive contributions to specifications, you must either participate 14 | in the relevant W3C Working Group or make a non-member patent licensing commitment. 15 | 16 | If you are not the sole contributor to a contribution (pull request), please identify all 17 | contributors in the pull request comment. 18 | 19 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 20 | 21 | ``` 22 | +@github_username 23 | ``` 24 | 25 | If you added a contributor by mistake, you can remove them in a comment with: 26 | 27 | ``` 28 | -@github_username 29 | ``` 30 | 31 | If you are making a pull request on behalf of someone else but you had no part in designing the 32 | feature, you can remove yourself with the above syntax. 33 | 34 | # Style guide to contributors 35 | 36 | - the spec uses [ReSpec](https://www.w3.org/respec/) 37 | - the spec is tidied using [HTML5 Tidy](https://github.com/w3c/tidy-html5). For 38 | instructions on running HTML5 tidy, see below. 39 | - put comments in front of sections, for better readability with 40 | syntax coloring editors. 41 | 42 | # Running HTML5 Tidy 43 | 44 | Please make sure you have HTML5 tidy installed, instead of 45 | the the one that ships with \*nix systems. You can comfirm this by running: 46 | 47 | ```bash 48 | tidy --version #HTML Tidy for HTML5 (experimental) for ... 49 | ``` 50 | 51 | Once you have confirmed (make sure you have committed your changes before 52 | running tidy, as the changes are destructive ... in a good way:)): 53 | 54 | ```bash 55 | tidy -config tidyconfig.txt -o index.html index.html 56 | ``` 57 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors 2 | under the [W3C Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Web Share Target API 2 | 3 | **Date**: 2016-06-08 4 | 5 | This site details a proposal to add a capability for websites to receive shared 6 | data from other sites and apps. 7 | 8 | * [Explainer document](docs/explainer.md), a high-level overview of the proposal. 9 | * [Specification - Level 1](https://w3c.github.io/web-share-target/). 10 | * [Specification - Level 2](https://w3c.github.io/web-share-target/level-2/). 11 | * [Native integration survey](docs/native.md), for platform-specific matters. 12 | 13 | This is a product of the [Ballista 14 | project](https://github.com/chromium/ballista), which aims to explore 15 | website-to-website and website-to-native interoperability. 16 | 17 | 18 | ## Licensing and contributions 19 | 20 | See [LICENSE](LICENSE.md) and [CONTRIBUTING](CONTRIBUTING.md). 21 | -------------------------------------------------------------------------------- /demos/images/README.md: -------------------------------------------------------------------------------- 1 | Icon source: [pixabay / 2 | ArtsyBee](https://pixabay.com/en/target-goal-business-icon-logo-1151287/) 3 | (Creative Commons CC0) 4 | -------------------------------------------------------------------------------- /demos/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-share-target/72dd80f90e24269804dd2ab6e9413eeb42935c5c/demos/images/favicon.ico -------------------------------------------------------------------------------- /demos/images/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-share-target/72dd80f90e24269804dd2ab6e9413eeb42935c5c/demos/images/icon-128.png -------------------------------------------------------------------------------- /demos/images/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-share-target/72dd80f90e24269804dd2ab6e9413eeb42935c5c/demos/images/icon-16.png -------------------------------------------------------------------------------- /demos/images/icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-share-target/72dd80f90e24269804dd2ab6e9413eeb42935c5c/demos/images/icon-180.png -------------------------------------------------------------------------------- /demos/images/icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-share-target/72dd80f90e24269804dd2ab6e9413eeb42935c5c/demos/images/icon-256.png -------------------------------------------------------------------------------- /demos/images/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-share-target/72dd80f90e24269804dd2ab6e9413eeb42935c5c/demos/images/icon-32.png -------------------------------------------------------------------------------- /demos/images/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-share-target/72dd80f90e24269804dd2ab6e9413eeb42935c5c/demos/images/icon-48.png -------------------------------------------------------------------------------- /demos/images/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-share-target/72dd80f90e24269804dd2ab6e9413eeb42935c5c/demos/images/icon-512.png -------------------------------------------------------------------------------- /demos/index.html: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |This is a test app for the Web 21 | Share Target API. It will only work in browsers that have implemented the 22 | draft proposal. At the time of writing, this works with:
23 |38 | This specification defines an API that allows websites to declare 39 | themselves as web share targets, which can receive shared 40 | content from either the [[[Web-Share]]], or system events (e.g., shares 41 | from native apps). 42 |
43 |44 | This is a similar mechanism to 45 | {{NavigatorContentUtils/registerProtocolHandler()}}, in that it works 46 | by registering the website with the user agent, to later be 47 | invoked from another site or native application via the user 48 | agent (possibly at the discretion of the user). The difference is that 49 | {{NavigatorContentUtils/registerProtocolHandler()}} registers the 50 | handler via a programmatic API, whereas a Web Share Target is declared 51 | in the [[[appmanifest]]], to be registered at a time of the user agent 52 | or user's choosing. 53 |
54 |57 | This is an early draft of the Web Share Target spec. 58 |
59 |65 | In order to implement this API, a the user agent MUST support 66 | [[[appmanifest]]]. This spec also re-uses some definitions from the 67 | [[[Web-Share]]] spec. However, support for the [[[Web-Share]]] is 68 | OPTIONAL. 69 |
70 |76 | To register a site as a share target, a [=manifest/share_target=] entry 77 | is added to the [[[appmanifest]]], as shown: 78 |
79 |80 | { 81 | "name": "Includinator", 82 | "share_target": { 83 | "action": "share.html", 84 | "params": { 85 | "title": "name", 86 | "text": "description", 87 | "url": "link" 88 | } 89 | } 90 | } 91 |92 |
93 | The [=ShareTarget/params=] keys correspond to the key names in 94 | {{ShareData}} from [[[Web-Share]]], while the values are arbitrary 95 | names that will be used as query parameters when the target is 96 | launched. 97 |
98 |99 | When a share takes place, if the user selects this share target, the 100 | user agent opens a new browsing context at the `action` URL, with query 101 | parameter values containing the shared data, just like an HTML form 102 | submission. 103 |
104 |105 | For the purpose of this example, we assume the manifest is located at 106 | `https://example.org/includinator/manifest.webmanifest`. 107 |
108 |109 | <html> 110 | <link rel="manifest" href="manifest.webmanifest"> 111 | <script> 112 | window.addEventListener('load', () => { 113 | const parsedUrl = new URL(window.location); 114 | const { searchParams } = parsedUrl; 115 | console.log("Title shared:", searchParams.get('name')); 116 | console.log("Text shared:", searchParams.get('description')); 117 | console.log("URL shared:", searchParams.get('link')); 118 | }); 119 | </script> 120 |121 |
122 | If an incoming share contains the title "My News" and the URL 123 | `http://example.com/news`, the user agent will open a new window or tab 124 | and navigate to: 125 |
126 |127 | https://example.org/includinator/share.html?name=My+News&link=http%3A%2F%2Fexample.com%2Fnews 128 |129 |
130 | U+0020 (SPACE) characters are encoded as "`+`", due to the use of 131 | [=`application\/x-www-form-urlencoded`=] encoding, not "`%20`" as might 132 | be expected. Processors must take care to decode U+002B (+) characters 133 | as U+0020 (SPACE), which some URL decoding libraries, including 134 | ECMAScript's `decodeURIComponent` 136 | function, may not do automatically. 137 |
138 |139 | The query parameters are populated with information from the 140 | {{ShareData}} being shared. If the {{ShareData}} contains no 141 | information for a given member, the query parameter is omitted. 142 |
143 |144 | A share target might only be interested in a subset of the 145 | {{ShareData}} members. This example also shows a share target that 146 | receives data as a `POST` request, which should be the case if the 147 | request causes an immediate side effect. 148 |
149 |150 | { 151 | "name": "Bookmark", 152 | "share_target": { 153 | "action": "/bookmark", 154 | "method": "POST", 155 | "enctype": "multipart/form-data", 156 | "params": { 157 | "url": "link" 158 | } 159 | } 160 | } 161 |162 |
163 | The shared information might be read by a [=service worker=], rather 164 | than being sent over the network to the server. 165 |
166 |167 | self.addEventListener("fetch", (event) => { 168 | if (event.request.method !== "POST") { 169 | event.respondWith(fetch(event.request)); 170 | return; 171 | } 172 | 173 | const formDataPromise = event.request.formData(); 174 | event.respondWith( 175 | formDataPromise.then((formData) => { 176 | const link = formData.get("link") || ""; 177 | saveBookmark(link); 178 | return new Response(`Bookmark saved: ${link}`); 179 | }) 180 | ); 181 | }); 182 |183 |
184 | How the handler deals with the shared data is at the handler's 185 | discretion, and will generally depend on the type of app. Here are some 186 | suggestions: 187 |
188 |209 | As a [=manifest=] is JSON, this specification relies on 211 | the types defined in the [[JSON]] specification: namely object and string. 214 |
215 |216 | The following steps are added to the [=processing extension-point of 217 | web manifest=]: 218 |
219 |
231 | The share_target
232 | member of the manifest is an [=object=]. When present, it declares
233 | this application to be a web share target, and describes how
234 | the application receives share data.
235 |
237 | A web share target is a web site with a 238 | valid [=manifest=] containing a [=manifest/share_target=] member. 239 |
240 |241 | A web share target is a type of share target (other types can 242 | be available, e.g., some system applications). 243 |
244 |245 | To process the `share_target` member given [=object=] 246 | |json:JSON| and [=ordered map=] |manifest:ordered map|: 247 |
248 |326 | The ShareTarget [=object=] can have the following members: 327 |
328 |action
member
331 | method
member
338 | enctype
member
351 | params
member
358 | 369 | The ShareTargetParams [=object=] can have the following 370 | members: 371 |
372 |title
375 | member
376 | text
383 | member
384 | url
member
392 | 405 | How and when web share targets are "registered" is at the 406 | discretion of the user agent and/or the end user. In fact, 407 | "registration" is a user-agent-specific concept that is not formally 408 | defined here; user agents are NOT REQUIRED to "register" web share 409 | targets at all; they are only REQUIRED to provide some mechanism to 410 | convey shared data to a web share target of the end user's choosing. 411 | User agents MAY consider a web share target "registered" even if it is 412 | not [=installed web application|installed=] 413 |
414 |415 | The user agent MAY automatically register all web share targets 416 | as the user visits the site, but it is RECOMMENDED that more discretion 417 | is applied, to avoid overwhelming the user with the choice of a large 418 | number of targets. 419 |
420 |422 | Examples of registration strategies that user agents can employ are: 423 |
424 |440 | When presenting the end user with a list of web share targets, 441 | the user agent MAY use an online service which has pre-indexed 442 | manifests, and therefore show the user targets that they have never 443 | visited or explicitly registered. 444 |
445 | 446 |452 | A web share target is invoked when the end user is sharing some 454 | data intended for a generic application, and indicates that specific 455 | web share target as the receiver of the data. 456 |
457 |458 | It is not specified where the data comes from, or how the end user 459 | indicates the web share target as the receiver. However, one possible 460 | source is a call to {{Navigator}}'s {{Navigator/share()}} method in the 461 | same user agent. 462 |
463 |465 | Examples of other possible sources of a web share target 466 | invocation are: 467 |
468 |484 | When a web share target is invoked, the data MAY be in 485 | an unspecified format. The user agent MUST first convert the data 486 | into a {{ShareData}} object, if it is not already, by mapping to the 487 | members of `ShareData` from equivalent concepts in the host system. 488 | If the source was a call to {{Navigator/share()}}, the user agent 489 | SHOULD use the {{ShareData}} argument unmodified (but this is not 490 | always possible, as it might have to round-trip through some other 491 | format in a lossy manner). The user agent MAY employ heuristics to 492 | map the data onto the `ShareData` fields as well as possible. 493 |
494 |495 | For example, the host share system may not have a dedicated URL 496 | field, but a convention that both plain text and URLs are sometimes 497 | transmitted in a "text" field. This is the case on Android. The user 498 | agent can check whether all or part of the "text" field is a [=valid 499 | URL string=], and if so, move that part of the "text" field to the 500 | {{ShareData}}'s {{ShareData/url}} member. 501 |
502 |508 | When web share target having [=ordered map=] |manifest| is 509 | invoked with {{ShareData}} |data|, run the following steps: 510 |
511 |593 | This algorithm assumes that |manifest| has had the [=process the 594 | `share_target` member=] algorithm run on it and still has a 595 | [=manifest/share_target=] afterwards. 596 |
597 |604 | This specification has no known accessibility considerations. 605 |
606 |646 | Thanks to the [[[WEBINTENTS]]] team, who laid the groundwork for the 647 | web app interoperability use cases. In particular, Paul Kinlan, who did a lot of early 649 | advocacy for Web Share and Web Share Target. 650 |
651 |652 | Thanks to Connie Pyromallis, who wrote an early draft of this spec, and 653 | helped design and prototype the API. 654 |
655 |656 | Thanks to Alex Russell and David Baron, for their feedback on early 657 | drafts of this spec. 658 |
659 |57 | This specification defines an API that allows websites to declare 58 | themselves as web share targets, which can receive shared 59 | content from either the Web Share API, or 60 | system events (e.g., shares from native apps). 61 |
62 |
63 | This is a similar mechanism to navigator.registerProtocolHandler
,
65 | in that it works by registering the website with the user agent, to
66 | later be invoked from another site or native application via the
67 | user agent (possibly at the discretion of the user). The difference is
68 | that registerProtocolHandler
70 | registers the handler via a programmatic API, whereas a Web Share
71 | Target is declared in the Web App
72 | Manifest, to be registered at a time of the user agent or user's
73 | choosing.
74 |
82 | In order to implement this API, it is REQUIRED that the user agent 83 | implements Web App Manifest. This spec 84 | also re-uses some definitions from the Web 85 | Share API spec. Implementation of that spec is NOT REQUIRED to 86 | implement this one (but it is RECOMMENDED). 87 |
88 |94 | To register a site as a share target, a share_target entry is 95 | added to the Web App Manifest, as shown: 96 |
97 |98 | { 99 | "name": "Includinator", 100 | "share_target": { 101 | "action": "share.html", 102 | "params": { 103 | "title": "name", 104 | "text": "description", 105 | "url": "link" 106 | } 107 | } 108 | } 109 |110 |
111 | The params keys correspond to the 112 | key names in ShareData from 113 | [[WebShare]], while the values are arbitrary names that will be used as 114 | query parameters when the target is launched. 115 |
116 |
117 | When a share takes place, if the user selects this share target, the
118 | user agent opens a new browsing context at the action
URL,
119 | with query parameter values containing the shared data, just like an
120 | HTML form submission.
121 |
123 | For the purpose of this example, we assume the manifest is located at
124 | https://example.org/includinator/manifest.webmanifest
.
125 |
127 | <html> 128 | <head> 129 | <link rel="manifest" href="manifest.webmanifest"> 130 | </head> 131 | <body> 132 | <script> 133 | window.addEventListener('load', () => { 134 | var parsedUrl = new URL(window.location); 135 | console.log('Title shared: ' + parsedUrl.searchParams.get('name')); 136 | console.log('Text shared: ' + parsedUrl.searchParams.get('description')); 137 | console.log('URL shared: ' + parsedUrl.searchParams.get('link')); 138 | }); 139 | </script> 140 | </body> 141 | </html> 142 |143 |
144 | If an incoming share contains the title "My News" and the URL
145 | http://example.com/news
, the user agent will open a new
146 | window or tab and navigate to:
147 |
149 | https://example.org/includinator/share.html?name=My+News&link=http%3A%2F%2Fexample.com%2Fnews 150 |151 |
152 | U+0020 (SPACE) characters are encoded as "+
", due to the
153 | use of application/x-www-form-urlencoded
155 | encoding, not "%20
" as might be expected. Processors must
156 | take care to decode U+002B (+) characters as U+0020 (SPACE), which some
157 | URL decoding libraries, including ECMAScript's decodeURIComponent
159 | function, may not do automatically.
160 |
162 | The query parameters are populated with information from the
163 | ShareData
being
164 | shared. If the ShareData contains no information for a given member,
165 | the query parameter is omitted.
166 |
168 | A share target might only be interested in a subset of the
169 | ShareData members. This
170 | example also shows a share target that receives data as a
171 | POST
request, which should be the case if the request
172 | causes an immediate side effect.
173 |
175 | { 176 | "name": "Bookmark", 177 | "share_target": { 178 | "action": "/bookmark", 179 | "method": "POST", 180 | "enctype": "multipart/form-data", 181 | "params": { 182 | "url": "link" 183 | } 184 | } 185 | } 186 |187 |
188 | The shared information might be read by a service worker, rather 190 | than being sent over the network to the server. 191 |
192 |193 | self.addEventListener('fetch', event => { 194 | if (event.request.method !== 'POST') { 195 | event.respondWith(fetch(event.request)); 196 | return; 197 | } 198 | 199 | event.respondWith((async () => { 200 | const formData = await event.request.formData(); 201 | const link = formData.get('link') || ''; 202 | const responseUrl = await saveBookmark(link); 203 | return Response.redirect(responseUrl, 303); 204 | })()); 205 | }); 206 |207 |
208 | A files entry in params is 209 | used to declare that files are accepted by the share target: 210 |
211 |212 | { 213 | "name": "Aggregator", 214 | "share_target": { 215 | "action": "/cgi-bin/aggregate", 216 | "method": "POST", 217 | "enctype": "multipart/form-data", 218 | "params": { 219 | "title": "name", 220 | "text": "description", 221 | "url": "link", 222 | "files": [ 223 | { 224 | "name": "records", 225 | "accept": ["text/csv", ".csv"] 226 | }, 227 | { 228 | "name": "graphs", 229 | "accept": "image/svg+xml" 230 | } 231 | ] 232 | } 233 | } 234 | } 235 |236 |
237 | The target will be invoked with a
238 | multipart/form-data
POST request, with field names as
239 | specified in params. Each shared file is assigned to the first files
240 | entry that accepts its MIME type. (The "POST"
241 | method
and "multipart/form-data"
242 | enctype
are necessary when file sharing, as with HTML
243 | forms.)
244 |
246 | How the handler deals with the shared data is at the handler's 247 | discretion, and will generally depend on the type of app. Here are some 248 | suggestions: 249 |
250 |title
252 | as the subject of an email, with text
and url
253 | concatenated together as the body, and files
as
254 | attachments.
255 | title
, using text
as the body of the message
258 | and adding url
as a link. Image files
would
259 | be accepted by MIME type or file extension, and attached to the post.
260 | If text
is missing, it might use url
in the
261 | body as well. If url
is missing, it might scan
262 | text
looking for a URL and add that as a link.
263 | title
and using text
and url
266 | concatenated together. It might truncate the text or replace
267 | url
with a short link to fit into the message size.
268 | 271 | As with HTML forms, replying to a POST request with a 303 See Other redirect is highly 273 | recommended, as it avoids the POST being submitted a second time if the 274 | user requests a page refresh. 275 |
276 |282 | The following IDL extends the WebAppManifest dictionary. 284 |
285 |286 | dictionary ShareTargetFiles { 287 | required USVString name; 288 | required (USVString or sequence<USVString>) accept; 289 | }; 290 | 291 | dictionary ShareTargetParams { 292 | USVString title; 293 | USVString text; 294 | USVString url; 295 | (ShareTargetFiles or sequence<ShareTargetFiles>) files; 296 | }; 297 | 298 | dictionary ShareTarget { 299 | required USVString action; 300 | DOMString method = "GET"; 301 | DOMString enctype = "application/x-www-form-urlencoded"; 302 | required ShareTargetParams params; 303 | }; 304 | 305 | partial dictionary WebAppManifest { 306 | ShareTarget share_target; 307 | }; 308 |309 |
310 | The following steps are added to the extension point in the steps for 312 | processing a 313 | manifest: 314 |
315 |share_target
member
318 | given manifest["share_target"],
319 | manifest["scope
"], and
321 | manifest URL.
322 | share_target
member
327 | 329 | The share_target member of the manifest is a 330 | ShareTarget dictionary that declares this application to be a 331 | web share target, and describes how the application receives 332 | share data. 333 |
334 |335 | A web share target is a web 336 | site with a valid manifest containing a share_target member. A 337 | web share target is a type of share target. 339 |
340 |
341 | The steps for post-processing the share_target
342 | member is given by the following algorithm. The algorithm takes
343 | a ShareTarget share target, a URL scope URL, and a URL manifest URL. This algorithm
346 | returns a ShareTarget or undefined
.
347 |
undefined
, then return
350 | undefined
.
351 | "GET"
nor "POST"
,
356 | issue a
357 | developer warning that the method is not supported, and return
358 | undefined
.
359 | "GET"
and share
364 | target["enctype"] is not an
365 | ASCII
366 | case-insensitive match for the string
367 | "application/x-www-form-urlencoded"
, issue a developer
369 | warning that the enctype is not supported with method GET, and
370 | return undefined
.
371 | "POST"
and share
376 | target["enctype"] is neither
377 | an ASCII
378 | case-insensitive match for the strings
379 | "application/x-www-form-urlencoded"
nor
380 | "multipart/form-data"
, issue a developer
382 | warning that the enctype is not supported, and return
383 | undefined
.
384 | "POST"
, or
400 | share target["enctype"]
401 | is not an ASCII
402 | case-insensitive match for the string
403 | "multipart/form-data"
, issue a developer
405 | warning that files are only supported with multipart/form-data
406 | POST, and return undefined
.
407 | /
subtype (where
441 | type and subtype are RFC7230 tokens)
443 | /*
(where type is a
446 | RFC7230 token)
447 | */*
450 | undefined
.
471 | undefined
.
479 | undefined
.
486 | ShareTarget
and its members
497 | 499 | The ShareTarget dictionary contains the following members. 500 |
501 |502 | The action member specifies the URL for the web share target. 505 |
506 |507 | The method member specifies the HTTP request method for the 509 | web share target. 510 |
511 |
512 | A use case for GET
requests is when the share target
513 | drafts a message for subsequent user approval. If the share target
514 | performs a side-effect without any user interaction,
515 | POST
requests should be used.
516 |
518 | The user agent MAY truncate the share data if method is
519 | "GET"
and an entry in the share data exceeds 2000 bytes.
520 |
522 | The enctype member specifies how the share data is encoded 523 | in the request. 524 |
525 |526 | The params member contains a ShareTargetParams 527 | dictionary. 528 |
529 |ShareTargetParams
and its members
534 | 536 | The ShareTargetParams dictionary contains the following 537 | members. 538 |
539 |540 | The title member specifies the name of the query parameter 541 | used for the title of the document being shared. 542 |
543 |544 | The text member specifies the name of the query parameter 545 | used for the arbitrary text that forms the body of the message being 546 | shared. 547 |
548 |549 | The url member specifies the name of the query parameter 550 | used for the URL string referring to a resource being shared. 551 |
552 |553 | The files member contains zero or more 554 | ShareTargetFiles dictionaries. 555 |
556 |ShareTargetFiles
and its members
561 | 563 | The ShareTargetFiles dictionary contains the following 564 | members. 565 |
566 |567 | The name member specifies the name of the form field used 568 | to share the files. 569 |
570 |571 | The accept member specifies a sequence of accepted MIME 572 | type(s) or file extension(s), the latter expressed as strings 573 | starting with U+002E FULL STOP (.). 574 |
575 |582 | How and when web share targets are "registered" is at the 583 | discretion of the user agent and/or the end user. In fact, 584 | "registration" is a user-agent-specific concept that is not formally 585 | defined here; user agents are NOT REQUIRED to "register" web share 586 | targets at all; they are only REQUIRED to provide some mechanism to 587 | convey shared data to a web share target of the end user's choosing. 588 | User agents MAY consider a web share target "registered" even if it is 589 | not installed. 590 |
591 |592 | The user agent MAY automatically register all web share targets 593 | as the user visits the site, but it is RECOMMENDED that more discretion 594 | is applied, to avoid overwhelming the user with the choice of a large 595 | number of targets. 596 |
597 |599 | Examples of registration strategies that user agents can employ are: 600 |
601 |navigator.registerProtocolHandler
).
611 | 617 | When presenting the end user with a list of web share targets, 618 | the user agent MAY use an online service which has pre-indexed 619 | manifests, and therefore show the user targets that they have never 620 | visited or explicitly registered. 621 |
622 | 623 |624 | An implementation supports filtering on MIME types if it 625 | takes into account the MIME types of the files being shared when 626 | presenting the user with a choice of share targets. 627 |
628 |629 | An implementation supports filtering on file extensions if 630 | it takes into account the extensions in the names of the files being 631 | shared when presenting the user with a choice of share targets. 632 |
633 |634 | An implementation MUST support filtering on MIME types or 635 | filtering on file extensions, or both. 636 |
637 |638 | If a file being shared is not accepted by any of a share 639 | target's files entries, the 640 | user MUST NOT be presented with that web share target as an option. 641 |
642 |648 | A web share target is invoked when the end user is sharing some 650 | data intended for a generic application, and indicates that specific 651 | web share target as the receiver of the data. 652 |
653 |
654 | It is not specified where the data comes from, or how the end user
655 | indicates the web share target as the receiver. However, one possible
656 | source is a call to navigator.share
in the
658 | same user agent.
659 |
662 | Examples of other possible sources of a web share target 663 | invocation are: 664 |
665 |title
" and the current page URL as
669 | "url
").
670 | ShareData
680 |
682 | When a web share target is invoked, the data MAY be in
683 | an unspecified format. The user agent MUST first convert the data
684 | into a ShareData
dictionary, if
686 | it is not already, by mapping to the fields of ShareData
687 | from equivalent concepts in the host system. If the source was a call
688 | to navigator.share
, the
690 | user agent SHOULD use the ShareData
argument
692 | unmodified (but this is not always possible, as it might have to
693 | round-trip through some other format in a lossy manner). The user
694 | agent MAY employ heuristics to map the data onto the
695 | ShareData
fields as well as possible.
696 |
698 | For example, the host share system may not have a dedicated URL
699 | field, but a convention that both plain text and URLs are sometimes
700 | transmitted in a "text" field. This is the case on Android. The user
701 | agent can check whether all or part of the "text" field is a
702 | valid URL string, and if so,
703 | move that part of the "text" field to the ShareData
's url
field.
706 |
713 | When web share target having WebAppManifest
714 | manifest is invoked with ShareData
data,
716 | run the following steps:
717 |
"title"
, "text"
, "url"
»,
730 | undefined
or an empty
736 | string, then continue.
737 | undefined
, then continue.
742 | "GET"
and
744 | value exceeds 2000 bytes in length, the user agent MAY
745 | set value to the first 2000 bytes of value.
746 | File
list
755 | pairs.
756 | "files"
],
771 | "GET"
:
815 | application/x-www-form-urlencoded
819 | serializer with entry list and no encoding
820 | override.
821 | "POST"
and
830 | enctype is "application/x-www-form-urlencoded"
:
831 | application/x-www-form-urlencoded
834 | serializer with entry list and no encoding
835 | override.
836 | "Content-Type"
/"application/x-www-form-urlencoded"
843 | to header list.
844 | "POST"
and
848 | enctype is "multipart/form-data"
:
849 |
852 | multipart/form-data
encoding algorithm with
853 | entry list and UTF-8
854 | encoding.
855 | "multipart/form-data;"
, a U+0020 SPACE character,
858 | the string "boundary="
, and the multipart/form-data
860 | boundary string generated by the multipart/form-data
862 | encoding algorithm.
863 | "Content-Type"
/MIME type to header
867 | list.
868 |
885 | This algorithm assumes that manifest has had the
886 | post-processing the share_target
member algorithm
887 | run on it and still has a share_target afterwards.
888 |
895 | The algorithm for determining if a ShareTargetFiles 896 | bucket accepts a 897 | File shared file 898 | is as follows:- 899 |
900 |"name"
] ends with criterion,
907 | and the implementation supports filtering on file
908 | extensions, return true
.
909 | /
subtype (where
912 | type and subtype are RFC7230 tokens) and matches the MIME
914 | type of shared file, and the implementation supports
915 | filtering on MIME types, return true
.
916 | /*
918 | (where type is a RFC7230 token) and the MIME type of
920 | shared file is a subtype of type
, and the
921 | implementation supports filtering on MIME types, return
922 | true
.
923 | */*
, return
925 | true
.
926 | false
.
930 | 973 | Thanks to the Web Intents team, who laid 974 | the groundwork for the web app interoperability use cases. In 975 | particular, Paul Kinlan, who did 976 | a lot of early advocacy for Web Share and Web Share Target. 977 |
978 |979 | Thanks to Connie Pyromallis, who wrote an early draft of this spec, and 980 | helped design and prototype the API. 981 |
982 |983 | Thanks to Alex Russell and David Baron, for their feedback on early 984 | drafts of this spec. 985 |
986 |