forked from w3c/web-share
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathindex.html
475 lines (475 loc) · 19.4 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>
Web Share API - Level 1
</title>
<script src="https://www.w3.org/Tools/respec/respec-w3c" class=
"remove"></script>
<script class='remove'>
var respecConfig = {
specStatus: "ED",
github: {
repoURL: "https://github.com/w3c/web-share/",
branch: "master"
},
testSuiteURI: "https://w3c-test.org/web-share/",
shortName: "web-share",
wg: "Web Applications Working Group",
wgURI: "https://www.w3.org/2019/webapps/",
editors: [{
name: "Matt Giuca",
company: "Google Inc.",
companyURL: "https://google.com",
w3cid: 91260
}],
caniuse: {
feature: "web-share",
browsers: ["chrome", "firefox", "safari", "edge", "and_chr", "and_ff", "ios_saf"],
},
xref: "web-platform",
};
</script>
</head>
<body>
<section id="abstract">
<p>
This specification defines an API for sharing text, links and other
content to an arbitrary destination of the user's choice.
</p>
<p>
The available share targets are not specified here; they are provided
by the user agent. They could, for example, be apps, websites or
contacts.
</p>
</section>
<section id="sotd">
<p>
This "Level 1" specification is relatively stable, with multiple
implementations. Future enhancements will be published as a separate
document.
</p>
</section>
<section class="informative">
<h2>
Usage Examples
</h2>
<p>
This example shows a basic share operation. In response to a button
click, this JavaScript code shares the current page's URL.
</p>
<pre class="example javascript" title="Basic usage">
shareButton.addEventListener("click", async () => {
try {
await navigator.share({ title: "Example Page", url: "" });
console.log("Data was shared successfully");
} catch (err) {
console.error("Share failed:", err.message);
}
});
</pre>
<p>
Note that a {{ShareData/url}} of `''` refers to the current page URL,
just as it would in a link. Any other absolute or relative URL can also
be used.
</p>
<p>
In response to this call to {{Navigator/share()}}, the user agent would
display a picker or chooser dialog, allowing the user to select a
target to share this title and the page URL to.
</p>
</section>
<section>
<h2>
API definition
</h2>
<section data-dfn-for="Navigator">
<h3>
`Navigator` interface
</h3>
<pre class="idl">
partial interface Navigator {
[SecureContext] Promise<void> share(optional ShareData data = {});
};
</pre>
<p>
User agents that do not support sharing SHOULD NOT expose
{{Navigator/share()}} on the <a>Navigator</a> interface.
</p>
<div class="note">
The above statement is designed to permit feature detection. If
{{Navigator/share()}} is present, there is a reasonable expectation
that it will work and present the user with at least one <a>share
target</a>. Clients can use the presence or absence of this method to
determine whether to show UI that triggers its use.
</div>
<section>
<h4>
Internal Slots
</h4>
<p>
This API adds the following internal slot to the {{Navigator}}
interface.
</p>
<dl>
<dt>
{{Promise}}? <dfn>[[\sharePromise]]</dfn>
</dt>
<dd>
The {{[[sharePromise]]}} is a promise that represents a user's
current intent to share some data with a <a>share target</a>. It
is initialized to `null`.
</dd>
</dl>
</section>
<section>
<h4>
<dfn>share()</dfn> method
</h4>
<p>
When the {{Navigator/share()}} method is called with argument
|data:ShareData|, run the following steps:
</p>
<ol class="algorithm">
<li>If {{[[sharePromise]]}} is not `null`, return <a>a promise
rejected with</a> {{InvalidStateError}}.
</li>
<li>If none of |data|'s members {{ShareData/title}},
{{ShareData/text}}, or {{ShareData/url}} are present, return <a>a
promise rejected with</a> a {{TypeError}}.
</li>
<li>If |data|'s {{ShareData/url}} member is [=dictionary
member/present=]:
<ol>
<li>Let |base:URL| be the <b>this</b> value's <a>relevant
settings object</a>'s [=environment settings object/api base
URL=].
</li>
<li>Let |url:URL| be the result of running the <a>URL
parser</a> on |data|'s {{ShareData/url}} with |base|.
</li>
<li>If |url| is failure, return <a>a promise rejected with</a>
{{TypeError}}.
</li>
<li>Set |data| to a copy of |data|, with its {{ShareData/url}}
member set to the result of running the <a>URL serializer</a>
on |url|.
</li>
</ol>
</li>
<li>If the method call was not <a>triggered by user activation</a>,
return <a>a promise rejected with</a> with a {{"NotAllowedError"}}
{{DOMException}}.
</li>
<li>Set {{[[sharePromise]]}} to be <a>a new promise</a>.
</li>
<li>Return {{[[sharePromise]]}} and <a>in parallel</a>:
<ol>
<li>If there are no <a>share targets</a> available:
<ol>
<li>
<a>Reject</a> {{[[sharePromise]]}} with an
"{{AbortError}}" {{DOMException}}.
</li>
<li>Set {{[[sharePromise]]}} to `null`.
</li>
<li>Abort these steps.
</li>
</ol>
</li>
<li>Present the user with a choice of one or more <a>share
targets</a>, selected at the user agent's discretion. The user
MUST be given the option to cancel rather than choosing any of
the share targets. Wait for the user's choice.
</li>
<li>If the user chose to cancel the share operation:
<ol>
<li>
<a>Reject</a> {{[[sharePromise]]}} with an
"{{AbortError}}" {{DOMException}},
</li>
<li>Set {{[[sharePromise]]}} to `null`.
</li>
<li>Abort these steps.
</li>
</ol>
</li>
<li>Activate the chosen <a>share target</a>, <a>convert |data|
to a format suitable for ingestion into the target</a>, and
transmit the converted data to the target.
</li>
<li>If an error occurs starting the target or transmitting the
data:
<ol>
<li>
<a>Reject</a> {{[[sharePromise]]}} with an
"{{DataError}}" {{DOMException}}.
</li>
<li>Set {{[[sharePromise]]}} to `null`.
</li>
<li>Abort these steps.
</li>
</ol>
</li>
<li>Once the data has been successfully transmitted to the
target, <a>resolve</a> {{[[sharePromise]]}} with `undefined`.
</li>
<li>Set {{[[sharePromise]]}} to `null`.
</li>
</ol>
</li>
</ol>
<p>
The user agent MUST NOT allow the website to learn which share
targets are available, or the identity of the chosen target.
</p>
<div class="note">
{{Navigator/share()}} always shows some form of UI, to give the
user a choice of application and get their approval to invoke and
send data to a potentially native application (which carries a
security risk). For this reason, user agents are prohibited from
showing any kind of "always use this target in the future" option,
or bypassing the UI if there is only a single share target.
</div>
</section>
</section>
<section data-dfn-for="ShareData">
<h3>
`ShareData` dictionary
</h3>
<pre class="idl">
dictionary ShareData {
USVString title;
USVString text;
USVString url;
};
</pre>
<p>
The <dfn>ShareData</dfn> dictionary consists of several optional
members:
</p>
<dl data-sort="">
<dt>
<dfn>title</dfn> member
</dt>
<dd>
The title of the document being shared. May be ignored by the
target.
</dd>
<dt>
<dfn>text</dfn> member
</dt>
<dd>
Arbitrary text that forms the body of the message being shared.
</dd>
<dt>
<dfn>url</dfn> member
</dt>
<dd>
A URL string referring to a resource being shared.
</dd>
</dl>
<div class="note">
These members are {{USVString}} (as opposed to {{DOMString}}) because
they are not allowed to contain invalid <a data-cite=
"rfc2781#section-2">UTF-16</a> surrogates. This means the user agent
is free to re-encode them in any Unicode encoding (e.g.,
<a data-cite="rfc3629#section-3">UTF-8</a>).
</div>
<div class="note">
The {{ShareData/url}} member can contain a <a>relative-URL
string</a>. In this case, it will be automatically resolved relative
to the current page location, just like a {{HTMLBaseElement/href}} on
an [^a^] element, before being given to the share target.
</div>
</section>
</section>
<section>
<h2>
Share targets
</h2>
<p>
A <dfn>share target</dfn> is the abstract concept of a destination that
the user agent will transmit the share data to. What constitutes a
share target is at the discretion of the user agent.
</p>
<p>
A share target might not be directly able to accept a {{ShareData}}
(due to not having been written with this API in mind). However, it
MUST have the ability to receive data that matches some or all of the
concepts exposed in {{ShareData}}. To <dfn>convert data to a format
suitable for ingestion into the target</dfn>, the user agent SHOULD map
the members of {{ShareData}} onto equivalent concepts in the target. It
MAY discard or combine members if necessary. The meaning of each member
of the payload is at the discretion of the share target.
</p>
<div class="note">
Mapping the {{ShareData}} to the share target's (or operating system's)
native format can be tricky as some platforms will not have an
equivalent set of members. For example, if the target has a "text"
member but not a "URL" member (as is the case on Android), one solution
is to concatenate both the {{ShareData/text}} and {{ShareData/url}}
members of {{ShareData}} and pass the result in the "text" member of
the target.
</div>
<p>
Each share target MAY be made conditionally available depending on the
{{ShareData}} payload delivered to the {{Navigator/share()}} method.
</p>
<div class="note">
Once a share target has been given the payload, the share is considered
successful. If the target considers the data unacceptable or an error
occurs, it can either recover gracefully, or show an error message to
the end-user; it cannot rely on the sender to handle errors. In other
words, the {{Navigator/share()}} method is "fire and forget"; it does
not wait for the target to approve or reject the payload.
</div>
<section class="informative">
<h3>
Examples of share targets
</h3>
<p>
The list of share targets can be populated from a variety of sources,
depending on the user agent and host operating system. For example:
</p>
<ul>
<li>Built-in service (e.g., "copy to clipboard").
</li>
<li>Native applications written for the host operating system.
</li>
<li>Contacts (e.g., the user agent directly shares to a person from
the user's address book, using a specific app).
</li>
<li>Websites (e.g., the user agent fills in a template URL with the
members of the {{ShareData}}, then navigates to that URL in a new
browsing context).
</li>
</ul>
<div class="note">
There is an attempt to standardize the registration of websites to
receive share data for that final use case; see <a href=
"https://github.com/WICG/web-share-target">Web Share Target</a>.
</div>
<p>
In some cases, the host operating system will provide a sharing or
intent system similar to Web Share. In these cases, the user agent
can simply forward the share data to the operating system and not
talk directly to native applications.
</p>
</section>
</section>
<section class="informative">
<h2>
Security and privacy considerations
</h2>
<p>
Web Share enables data to be sent from websites to native applications.
While this ability is not unique to Web Share, it does come with a
number of potential security issues that can vary in severity
(depending on the underlying platform).
</p>
<ul>
<li>There is a requirement to not allow the website to learn which apps
are installed, or which app was chosen from {{Navigator/share()}},
because this information could be used for fingerprinting, as well as
leaking details about the user's device.
</li>
<li>Implementors will want to carefully consider what information is
revealed in the error message when {{Navigator/share()}} is rejected.
Even distinguishing between the case where no targets are available and
user cancellation could reveal information about which apps are
installed on the user's device.
</li>
<li>There is a requirement that {{Navigator/share()}} presents the user
with a dialog asking them to select a target application (even if there
is only one possible target). This surface serves as a security
confirmation, ensuring that websites cannot silently send data to
native applications.
</li>
<li>Due to the capabilities of the API surface, {{Navigator/share()}}
is <a>available only in secure contexts</a> (such as `https://`
schemes).
</li>
<li>Use of {{Navigator/share()}} from a <a href=
"https://en.wikipedia.org/wiki/Privacy_mode">private browsing mode</a>
might leak private data to a third-party application that does not
respect the user's privacy setting. User agents could present
additional warnings or disable the feature entirely when in a private
browsing mode, but this is not mandated as the chooser UI could be
considered sufficient warning.
</li>
<li>The data passed to {{Navigator/share()}} might be used to exploit
buffer overflow or other remote code execution vulnerabilities in
native applications that receive shares. There is no general way to
guard against this, but implementors will want to be aware that it is a
possibility.
</li>
</ul>
</section>
<section class="appendix informative">
<h2>
Extensibility of this API
</h2>
<p>
The Web Share API is designed to be extended in the future by way of
new members added to the {{ShareData}} dictionary, to allow both
sharing of new types of data (<i>e.g.</i>, <a href=
"https://github.com/w3c/web-share/issues/12">images</a>) and strings
with new semantics (<i>e.g.</i> author).
</p>
<div class="warning">
This doesn't mean user agents can add whatever members they like. It
means that new members can be added to the standard in the future.
</div>
<p>
The three members {{ShareData/title}}, {{ShareData/text}}, and
{{ShareData/url}}, are part of the base feature set, and
implementations that provide {{Navigator/share()}} need to accept all
three. Any new members that are added in the future will be
<em>individually feature-detectable</em>, to allow for
backwards-compatibility with older implementations that don't recognize
those members. These new members might also be added as optional "MAY"
requirements.
</p>
<div class="note">
There is <a href="https://github.com/heycam/webidl/issues/107">an open
discussion</a> about how to provide feature-detection for dictionary
members. Web Share will use the mechanism produced by that discussion.
</div>
<p>
The {{Navigator/share()}} method returns a rejected promise with a
{{TypeError}} if none of the specified members are present. The
intention is that when a new member is added, it will also be added to
this list of recognized members. This is for future-proofing
implementations: if a web site written against a future version of this
spec uses <em>only</em> new members (<i>e.g.</i>,
`navigator.share({image: x})`), it will be valid in future user agents,
but a {{TypeError}} on user agents implementing an older version of the
spec. Developers will be asked to feature-detect any new members they
rely on, to avoid having errors surface in their program.
</p>
<p>
Editors of this spec will want to carefully consider the genericity of
any new members being added, avoiding members that are closely
associated with a particular service, user agent or operating system,
in favour of members that can potentially be applied to a wide range of
platforms and targets.
</p>
</section>
<section id="conformance"></section>
<section id="idl-index"></section>
<section class="appendix">
<h2>
Acknowledgments
</h2>
<p>
Thanks to the <a href="https://www.w3.org/TR/web-intents">Web
Intents</a> team, who laid the groundwork for the web app
interoperability use cases. In particular, <a href=
"https://paul.kinlan.me/">Paul Kinlan</a>, who did a lot of early
advocacy for Web Share.
</p>
</section>
</body>
</html>