-
Notifications
You must be signed in to change notification settings - Fork 65
/
Copy pathindex.html
870 lines (867 loc) · 35.8 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
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>
Web Share API
</title>
<script src="https://www.w3.org/Tools/respec/respec-w3c" class=
"remove"></script>
<script class='remove'>
var respecConfig = {
shortName: "web-share",
previousMaturity: "PR",
specStatus: "ED",
github: {
repoURL: "w3c/web-share",
branch: "main"
},
testSuiteURI: "https://wpt.live/web-share/",
group: "webapps",
editors: [{
name: "Matt Giuca",
company: "Google Inc.",
companyURL: "https://google.com",
w3cid: 91260
},
{
name: "Eric Willigers",
company: "Google Inc.",
companyURL: "https://google.com",
w3cid: 67534
},
{
name: "Marcos Cáceres",
company: "Apple Inc.",
companyURL: "https://apple.com",
w3cid: 39125,
}],
caniuse: {
feature: "web-share",
browsers: ["chrome", "firefox", "safari", "edge", "and_chr", "and_ff", "ios_saf"],
},
implementationReportURI: "https://w3c.github.io/web-share/imp-report/",
xref: "web-platform",
mdn: true,
crEnd: "2022-09-20",
prEnd: "2023-04-12",
errata: "https://github.com/w3c/web-share/labels/errata",
};
</script>
</head>
<body data-cite="FILEAPI">
<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" class="updateable-rec">
<section class="informative">
<h3>
Implementation status
</h3>
<p>
The ability to share content is often dependent on the underlying
operating system providing a "share" capability and also on OS UI
conventions. For example, some OSs present a "share sheet", while
others rely on an pop-up menu. Due to these aforementioned
dependencies, there is ongoing work by implementers to bring the Web
Share API to all OSs. This ongoing effort is reflected as failures in
the <a href="https://wpt.fyi/web-share">implementation report</a>,
which is generated by running tests on a limited set of OSs. However,
the Working Group is optimistic that the Web Share API will become
more available across all OSs over time, and is already widely
available on popular OSs across a range of devices.
</p>
</section>
</section>
<section class="informative">
<h2>
Usage Examples
</h2>
<h3>
Sharing text and links
</h3>
<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="Sharing text and URL">
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>
<h3>
Sharing a file
</h3>
<p>
This example shows how to share a file. Note that the
{{ShareData/files}} member is an array, allowing for multiple files to
be shared.
</p>
<pre class="example javascript" title="Sharing a file">
shareButton.addEventListener("click", async () => {
const file = new File(data, "some.png", { type: "image/png" });
try {
await navigator.share({
title: "Example File",
files: [file]
});
} catch (err) {
console.error("Share failed:", err.message);
}
});
</pre>
<h3>
Validating a share
</h3>
<p>
Calling {{Navigator/canShare()}} method with a {{ShareData}} dictionary
[=validate share data|validates=] the shared data. Unlike
{{Navigator/share()}}, it can be called without [=transient
activation=].
</p>
<pre class="js example">
const file = new File([], "some.png", { type: "image/png" });
// Check if files are supported
if (navigator.canShare({files: [file]})) {
// Sharing a png file would probably be ok...
}
// Check if a URL is ok to share...
if (navigator.canShare({ url: someURL })) {
// The URL is valid and can probably be shared...
}
</pre>
<h3>
Checking if members are supported
</h3>
<p>
Because of how WebIDL dictionaries work, members passed to
{{Navigator/share()}} that are unknown to the user agent are ignored.
This can be a problem when sharing multiple members, but the user agent
doesn't support sharing one of those members. To be sure that every
member being passed is supported by the user agent, you can pass them
to {{Navigator/canShare()}} individually to check if they are
supported.
</p>
<pre class="js example" title="Future-proofing shares">
const data = {
title: "Example Page",
url: "https://example.com",
text: "This is a text to share",
someFutureThing: "some future thing",
};
const allSupported = Object.entries(data).every(([key, value]) => {
return navigator.canShare({ [key]: value });
});
if (allSupported) {
await navigator.share(data);
}
</pre>
<p>
Alternatively, you can adjust application's UI to not show UI
components for unsupported members.
</p>
<pre class="js example" title="Filtering out unsupported members">
const data = {
title: "Example Page",
url: "https://example.com",
text: "This is a text to share",
someFutureThing: "some future thing",
};
// Things that are not supported...
const unsupported = Object.entries(data).filter(([key, value]) => {
return !navigator.canShare({ [key]: value });
});
</pre>
<h3>
Enabling the API in third-party contexts
</h3>
<p data-cite="permissions-policy">
The [=policy-controlled feature/default allowlist=] of [=default
allowlist/'self'=] makes Web Share API available by default only in
first-party contexts.
</p>
<p>
Third-party can be allowed to use this API via an [^iframe^]'s
[^iframe/allow^] attribute:
</p>
<aside class="example" title=
"Enabling the web-share API in a third-party context">
<pre class="html">
<iframe
src="https://third-party.example"
allow="web-share">
</iframe>
</pre>
</aside>
<p>
Alternatively, the API can be disabled in a first-party context by
specifying an HTTP response header:
</p>
<aside class="example" title=
"Disabling Web Share over API HTTP using Permissions Policy">
<pre class="http">
Permissions-Policy: web-share=()
</pre>
</aside>
<p>
See the [[[permissions-policy]]] specification for more details and for
how to control the permission policies on a per-origin basis.
</p>
</section>
<section>
<h2>
API definition
</h2>
<section data-dfn-for="Navigator">
<h3>
Extensions to the `Navigator` interface
</h3>
<pre class="idl">
partial interface Navigator {
[SecureContext] Promise<undefined> share(optional ShareData data = {});
[SecureContext] boolean canShare(optional ShareData data = {});
};
</pre>
<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 [=this=].{{Navigator/[[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 listed steps listed below while taking
into consideration the following security implications.
</p>
<p>
Web Share enables data to be sent from websites to a [=share
target=], which can be a native applications. While this ability is
not unique to Web Share, it does come with a number of potential
security risks that can vary in severity (depending on the
underlying platform).
</p>
<p>
The data passed to {{Navigator/share()}} might be used to exploit
buffer overflow or other remote code execution vulnerabilities in
the [=share target=] that receive shares. There is no general way
to guard against this, but implementors will want to be aware that
it is a possibility (particularly when sharing files).
</p>
<p>
[=Share targets=] that dereference a shared URL and forward that
information on might inadvertently forward information that might
be otherwise confidential. This can lead to unexpected information
leakage if shares reference content that is only accessible by that
application, the host on which it runs, or its network location.
</p>
<p>
Malicious sites might exploit share targets that leak information
by providing URLs that ultimately resolve to local resources,
including, but not limited to, "file:" URLs or local services that
might otherwise be inaccessible. Even though this API limits shared
URLS to a restricted set of [=sharable schemes=], use of redirects
to other URLs or tweaks to DNS records for hosts in those URLs
might be used to cause applications to acquire content.
</p>
<p>
To avoid being used in these attacks, share targets can consume the
URL, retrieve the content, and process that information without
sharing it. For instance, a photo editing application might
retrieve an image that is "shared" with it. A share target can also
share the URL without fetching any of the referenced content.
</p>
<p>
Share targets that fetch content for the purposes of offering a
preview or for sharing content risk information leakage. Content
that is previewed and authorized by a user might be safe to
forward, however it is not always possible for a person to identify
when information should be confidential, so forwarding any content
presents a risk. In particular, the {{ShareData/title}} might be
used by an attacker to trick a user into misinterpreting the nature
of the content (see also [[[#a11y]]]).
</p>
<p>
As with any user of {{DOMException}}, implementors need to
carefully consider what information is revealed in the error
message when {{Navigator/share()}} is rejected. Even distinguishing
between the case where no [=share targets=] are available and user
cancellation could reveal information about which share targets are
installed on the user's device.
</p>
<ol class="algorithm">
<li>Let |global:Window| be [=this=]'s [=relevant global object=].
</li>
<li>Let |document:Document| be |global|'s [=associated
`Document`=].
</li>
<li>If |document| is not [=Document/fully active=], return [=a
promise rejected with=] an {{"InvalidStateError"}}
{{DOMException}}.
</li>
<li>If |document| is not <a>allowed to use</a> <a>"web-share"</a>,
return [=a promise rejected with=] a {{"NotAllowedError"}}
{{DOMException}}.
</li>
<li>If [=this=].{{Navigator/[[sharePromise]]}} is not `null`,
return [=a promise rejected with=] an {{"InvalidStateError"}}
{{DOMException}}.
</li>
<li>If |global| does not have [=transient activation=], return [=a
promise rejected with=] a {{"NotAllowedError"}} {{DOMException}}.
</li>
<li>[=Consume user activation=] of |global|.
</li>
<li>Let |base:URL| be [=this=]'s <a>relevant settings object</a>'s
[=environment settings object/API base URL=].
</li>
<li>If [=validate share data=] with |data| and |base| returns
false, then return [=a promise rejected with=] a {{TypeError}}.
</li>
<li>If |data|'s {{ShareData/url}} member is present:
<ol>
<li>Let |url:URL| be the result of running the <a>URL
parser</a> on |data|'s {{ShareData/url}} with |base|.
</li>
<li>Assert: |url| is {{URL}}.
</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 a file type is being blocked due to security considerations,
return [=a promise rejected with=] a {{"NotAllowedError"}}
{{DOMException}}.
</li>
<li>Set [=this=].{{Navigator/[[sharePromise]]}} to be <a>a new
promise</a>.
</li>
<li>Return [=this=].{{Navigator/[[sharePromise]]}} and <a>in
parallel</a>:
<ol>
<li>If there are no <a>share targets</a> available, [=queue a
global task=] on the [=user interaction task source=] using
|global| to:
<ol>
<li>[=Reject=] [=this=].{{Navigator/[[sharePromise]]}} with
an {{"AbortError"}} {{DOMException}}.
</li>
<li>Set [=this=].{{Navigator/[[sharePromise]]}} to `null`.
</li>
<li>Terminate this algorithm.
</li>
</ol>
</li>
<li>Present the user with a choice of one more <a>share
targets</a> and the ability abort the operation. This UI
surface serves as a security confirmation, ensuring that
websites cannot silently send data to native applications. The
user agent SHOULD show intermediary UI through which the user
can verify the shared content (if the OS-level UI does not
provide this functionality).
</li>
<li>Wait for the user's choice.
</li>
<li>If the user chose to abort the share operation, [=queue a
global task=] on the [=user interaction task source=] using
|global| to:
<ol>
<li>[=Reject=] [=this=].{{Navigator/[[sharePromise]]}} with
an {{"AbortError"}} {{DOMException}},
</li>
<li>Set [=this=].{{Navigator/[[sharePromise]]}} to `null`.
</li>
<li>Terminate this algorithm.
</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, [=queue a global task=] on the [=user interaction task
source=] using |global| to:
<ol>
<li>[=Reject=] [=this=].{{Navigator/[[sharePromise]]}} with
an {{"DataError"}} {{DOMException}}.
</li>
<li>Set [=this=].{{Navigator/[[sharePromise]]}} to `null`.
</li>
<li>Terminate this algorithm.
</li>
</ol>
</li>
<li>Once the data has either been successfully transmitted to
the [=share target=], or successfully transmitted to the OS (if
the transmission to the [=share target=] cannot be confirmed),
[=queue a global task=] on the [=user interaction task source=]
using |global| to:
<aside 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.
</aside>
<ol>
<li>[=Resolve=] [=this=].{{Navigator/[[sharePromise]]}}
with `undefined`.
</li>
<li>Set [=this=].{{Navigator/[[sharePromise]]}} to `null`.
</li>
</ol>
</li>
</ol>
</li>
</ol>
</section>
<section>
<h3>
`canShare(data)` method
</h3>
<p>
When the <dfn>canShare()</dfn> method is called with argument
{{ShareData}} |data:ShareData|, run the following steps:
</p>
<ol class="algorithm">
<li>Let |document:Document| be the [=this=]'s [=relevant global
object=]'s [=associated `Document`=].
</li>
<li>If |document| is not [=Document/fully active=], return false.
</li>
<li>If |document| is not <a>allowed to use</a> <a>"web-share"</a>,
return false.
</li>
<li>Return the result of [=validate share data=] with |data| and
[=this=]'s [=relevant settings object=]'s [=environment settings
object/API base URL=].
</li>
</ol>
<aside class="note" title="canShare() is not future compatible">
<p>
The `canShare()` method of the Web Share API may return false
positive results when used with objects that contain members not
defined in the `ShareData` dictionary. Because of how WebIDL
works, browsers drop unknown members from the input object and
will return `true` when testing the remaining members. This
behavior is not future-compatible.
</p>
<p>
To ensure reliable testing of shareability, developers can
construct the input object using only members defined in the
{{ShareData}} dictionary. If an object contains additional
members, it should be destructured to only test the defined
members individually.
</p>
<p>
Although this doesn't affect any implementations today, the
Working Group will work towards addressing this issue in a future
revision of the specification - especially if we make any
amendments to the `ShareData` dictionary. To contribute ideas for
how to address this issue, see <a href=
"https://github.com/w3c/web-share/issues/108">issue #108</a> on
GitHub.
</p>
</aside>
</section>
<section>
<h3>
Validate share data
</h3>
<p>
A <dfn>sharable scheme</dfn> is any of the following [=URL=]
[=URL/schemes=]:
</p>
<ul>
<li>`http`
</li>
<li>`https`
</li>
<li>Any [=safelisted scheme=] that the user agent supports for the
purpose of sharing.
</li>
</ul>
<p>
To <dfn>validate share data</dfn> with |data:ShareData| and
|base:URL|, run the following steps:
</p>
<ol class="algorithm">
<li>If none of |data|'s members {{ShareData/title}},
{{ShareData/text}}, or {{ShareData/url}} or {{ShareData/files}} are
present, return false.
</li>
<li>Let |titleTextOrUrl:boolean| be true if any of
{{ShareData/title}}, or {{ShareData/text}}, or {{ShareData/url}} is
present.
</li>
<li>If |data|'s {{ShareData/files}} member is present:
<ol>
<li>If |titleTextOrUrl| is false and |data|'s
{{ShareData/files}} member is empty, return false.
<p class="note">
This causes a `{ files: [] }` dictionary to be treated as
an empty dictionary. However, passing a dictionary like
`{text: "text", files: []}` is fine, as `files` is just
ignored.
</p>
</li>
<li>If the implementation does not support file sharing, return
false.
</li>
<li>If the user agent believes sharing any of the files in
`files` would result in a potentially hostile share (i.e., the
user agent determines a file is malicious in some way, because
of its contents, size, or other characteristic), return false.
</li>
</ol>
</li>
<li>If |data|'s {{ShareData/url}} member is present:
<ol>
<li>Let |url:URL| be the result of running the [=URL parser=]
on |data|'s {{ShareData/url}} member, with |base|, and no
encoding override.
</li>
<li>If |url| is failure, return false.
</li>
<li>If the |url|'s [=URL/scheme=] is a [=local scheme=], or
`file`, or `javascript`, or `ws`, or `wss`, return false.
</li>
<li>If |url|'s [=URL/scheme=] is not a [=sharable scheme=],
return false.
</li>
</ol>
</li>
<li>Return true.
</li>
</ol>
</section>
</section>
<section data-dfn-for="ShareData">
<h3>
`ShareData` dictionary
</h3>
<pre class="idl">
dictionary ShareData {
sequence<File> files;
USVString title;
USVString text;
USVString url;
};
</pre>
<p>
The <dfn>ShareData</dfn> dictionary consists of several optional
members:
</p>
<dl data-sort="">
<dt>
<dfn>files</dfn> member
</dt>
<dd>
Files to be shared.
</dd>
<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>
<aside class="note" data-cite="encoding">
These members are {{USVString}} (as opposed to {{DOMString}}) because
they are not allowed to contain surrogate code points. Among other
things, this means that the user agent can serialize them into any
Unicode encoding, such as [=UTF-8=], without change or loss of data
or the generation of replacement characters.
</aside>
</section>
</section>
<section>
<h2>
Share targets
</h2>
<p>
A <dfn data-export="">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>
<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/w3c/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 id="permissions-policy" data-cite="permissions-policy">
<h2>
Permissions Policy integration
</h2>
<p>
This specification defines a policy-controlled permission identified by
the string <code><dfn class="permission">"web-share"</dfn></code>. Its
[=policy-controlled feature/default allowlist=] is [=default
allowlist/'self'=], which means third-party contexts are not [=allowed
to use=] the API by default.
</p>
<p>
It is OPTIONAL for user agents to support [[[PERMISSIONS-POLICY]]]'s
`Permissions-Policy` HTTP header.
</p>
<p>
Developers can use the means afforded by the [[[permissions-policy]]]
specification to control if and when a third-party context is [=allowed
to use=] this API.
</p>
<aside class="note" title="Permissions Policy Implementation Status">
<p>
Although user agents are unified in preventing the Web Share API from
being used in third-party context, at the time of publication there
are interoperability issues with relying on the
[[[Permissions-Policy]]] to enable the API in third-party contexts.
In particular, although the[^iframe/allow^] attribute is widely
supported, the updated syntax for the [^iframe/allow^] attribute is
not. Similarly, the `Permissions-Policy:` HTTP header is not yet
widely supported. Developers are advised to check the implementation
status of the [[[Permissions-Policy]]] specification before relying
on it to enable the Web Share API in third-party contexts.
</p>
<p>
When the `Permissions-Policy` HTTP header is more widely supported,
the Working Group expects to revise this specification to require
support for the header.
</p>
</aside>
</section>
<section class="informative" id="a11y">
<h2>
Accessibility considerations
</h2>
<p>
When this specification is used to present information in the user
interface, implementors will want to follow the OS level accessibility
guidelines for the platform. Further, as sharing can have potential
security implications for end-users, as outlined as part of the
{{Navigator/share()}} method, the share UI needs to be presented in an
accessible manner, while also taking into consideration a platform's
security guidelines for user interfaces. Some key considerations are
to:
</p>
<ul>
<li>Provide alternative text for images and other non-textual content
to ensure that users who are visually impaired can understand the type
and/or nature of the content being shared.
</li>
<li>Ensure that users can navigate through the previewed content using
keyboard-only controls, and that the keyboard focus is clearly visible.
</li>
<li>Use headings and labels to ensure that the previewed content is
properly structured and can be understood by users using assistive
technology.
</li>
<li>Ensure sufficient color contrast and font size, and use fonts,
icons, and images that are widely recognised and easily understood, in
the share UI.
</li>
</ul>
<p>
Together, these elements can help users with a range of visual, motor
or cognitive disabilities to better understand the nature of the
content being shared by a web page.
</p>
</section>
<section>
<h2>
Privacy considerations
</h2>
<ul>
<li>By design, the API cannot be used by a website to learn which
[=share targets=] are available, or which share target the user chose
from {{Navigator/share()}}. This is to prevent leaking information that
could be used for fingerprinting, as well as leaking details about the
user's device or user's preferred share targets.
</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 MAY 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>
</ul>
</section>
<section id="conformance"></section>
<section id="idl-index"></section>
<section class="informative">
<h2>
Changelog
</h2>
<p>
The following normative changes were made to the specification during
the <a href=
"https://www.w3.org/TR/2022/PR-web-share-20221215/">Proposed
Recommendation</a> phase. Please see the <a href=
"https://github.com/w3c/web-share/commits/main">commit log</a> for a
complete list of changes.
</p><rs-changelog from="PR" to="e441b96ded837660e826e702b7e041f7f0f15751"
filter="removeCommits"></rs-changelog>
<p>
The following normative changes were made to the specification since it
was published as a <a href=
"https://www.w3.org/TR/2019/WD-web-share-20191217/">First Public
Working Draft</a> to Candidate Recommendation. Please see the <a href=
"https://github.com/w3c/web-share/commits/main">commit log</a> for a
complete list of changes.
</p>
<script class="remove">
const ignoredHashes = [
"2ed0b468aacf7a4e3e351f25f114e9cb2fbef009",
"9226ea59cb497ee02cf3235f142439c7277a4887",
"ac3022d8f3161b733f321c4821d87b0d27dc4171",
"ed052537bdf962db72b6d7fd778df42090f96341",
"66856684ec497a6a71da5889039cd3fae0e868c6",
"3801fcf710a91e9861fc6be6a0f2fc0b180618b3",
];
function removeCommits(entry) {
const { message, hash } = entry;
for (const ignoredHash of ignoredHashes) {
if (ignoredHash.startsWith(hash)) {
return false;
};
}
return !/^editorial|^chore|^\[chore|^fix|^refactor|^tests?|^docs|^typo|^nit/i.test(message);
}
</script> <rs-changelog from="1589731080e09b9c7d485e54340ba66bc3ae1be0"
to="CR" filter="removeCommits"></rs-changelog>
</section>
<section class="appendix">
<h2>
Acknowledgments
</h2>
<p>
The editors would like to thank the following W3C groups for their
invaluable feedback, which greatly improved this specification:
<a href="https://www.w3.org/WAI/APA/">Accessible Platform Architectures
Working Group</a>, the <a href=
"https://www.w3.org/International/i18n-activity/i18n-wg/">Internationalization
Working Group</a>, the <a href="https://www.w3.org/Privacy/IG/">Privacy
Interest Group</a>, and the <a href="https://tag.w3.org">Technical
Architecture Group</a>.
</p>
<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>