-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add canShare() method #177
Changes from 10 commits
0331a1c
a130e8d
f36224b
0ec77e9
53bf3f0
fc20b1b
32bfa3e
fdd10df
f38862e
d4853d8
6c04cb2
7828d97
07322d5
5dc2244
7875616
cca9754
cad9d6e
b3ef905
338d7fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,7 +47,7 @@ | |
}; | ||
</script> | ||
</head> | ||
<body data-cite="FILEAPI"> | ||
<body data-cite="FILEAPI secure-contexts mimesniff"> | ||
<section id="abstract"> | ||
<p> | ||
This specification defines an API for sharing text, links and other | ||
|
@@ -93,17 +93,24 @@ <h2> | |
target to share this title and the page URL to. | ||
</p> | ||
</section> | ||
<section> | ||
<section data-dfn-for="Navigator"> | ||
<h2> | ||
API definition | ||
</h2> | ||
<section data-dfn-for="Navigator"> | ||
<section> | ||
<h3> | ||
Extensions to the `Navigator` interface | ||
</h3> | ||
<pre class="idl"> | ||
partial interface Navigator { | ||
[SecureContext] Promise<undefined> share(optional ShareData data = {}); | ||
[SecureContext] | ||
Promise<undefined> share(optional ShareData data = {}); | ||
|
||
[SecureContext] | ||
boolean canShare(optional ShareData data = {}); | ||
|
||
[SecureContext] | ||
boolean canShare(DOMString name, optional CanShareQuery options = {}); | ||
}; | ||
</pre> | ||
<p> | ||
|
@@ -145,10 +152,10 @@ <h4> | |
|data:ShareData|, run the following steps: | ||
</p> | ||
<ol class="algorithm"> | ||
<li>If the current settings object's responsible document is not | ||
<a>allowed to use</a> the "[=web-share-feature|web-share=]" | ||
permission, return [=a promise rejected with=] with a | ||
{{"NotAllowedError"}} {{DOMException}}. | ||
<li>If the [=current settings object=]'s [=environment settings | ||
object/responsible document=] is not <a>allowed to use</a> the | ||
"[=web-share-feature|web-share=]" permission, return [=a promise | ||
rejected with=] with a {{"NotAllowedError"}} {{DOMException}}. | ||
</li> | ||
<li>If {{[[sharePromise]]}} is not `null`, return <a>a promise | ||
rejected with</a> {{InvalidStateError}}. | ||
|
@@ -165,28 +172,19 @@ <h4> | |
{{ShareData/text}}, or {{ShareData/url}} or {{ShareData/files}} are | ||
present, return <a>a promise rejected with</a> a {{TypeError}}. | ||
</li> | ||
<li>If |data|'s {{ShareData/files}} member is present: | ||
<ol> | ||
<li>If |data|'s {{ShareData/files}} member is empty, or if the | ||
implementation does not support file sharing, return <a>a | ||
promise rejected with</a> a {{TypeError}}, and abort these | ||
steps. | ||
</li> | ||
</ol> | ||
<li>Let |base:URL| be the [=this=] value's <a>relevant settings | ||
object</a>'s [=environment settings object/api base URL=]. | ||
</li> | ||
<li>If running the steps to [=validate share data=] with |data| and | ||
|base| return false, then return a promise rejected with a | ||
{{TypeError}}. | ||
</li> | ||
<li>If |data|'s {{ShareData/url}} member is present: | ||
<ol> | ||
<li>Let |base:URL| be the [=this=] 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>If |url|'s [=URL/scheme=] is not "http" or "https", return | ||
<a>a promise rejected with</a> {{TypeError}}. | ||
<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> | ||
|
@@ -269,6 +267,110 @@ <h4> | |
or bypassing the UI if there is only a single share target. | ||
</div> | ||
</section> | ||
<section> | ||
<h3> | ||
`canShare(data)` method | ||
</h3> | ||
<aside class="note" title="When to use canShare(data)"> | ||
<p> | ||
Calling {{Navigator/canShare()}} method with a {{ShareData}} | ||
dictionary [=validate share data|validates=] the shared data. It | ||
also works without requiring a user gesture, so, unlike | ||
{{Navigator/share()}}, it doesn't [=consume user activation=]. | ||
</p> | ||
<pre class="example"> | ||
// Check if files are supported | ||
const file = new File([], "some.png", { type: "image/png" }); | ||
if (navigates.canShare({files: [file]})) { | ||
// Sharing a png file would probably be ok... | ||
} | ||
|
||
// Check if a URL is ok to share... | ||
if (navigates.canShare({ url: someURL })) { | ||
// The URL is valid and can probably be shared... | ||
} | ||
</pre> | ||
</aside> | ||
<p> | ||
When the <dfn data-lt="canShare()">canShare(data)</dfn> method is | ||
called with argument {{ShareData}} |data:ShareData|, run the | ||
following steps: | ||
</p> | ||
<ol class="algorithm"> | ||
<li>If the [=current settings object=]'s [=environment settings | ||
object/responsible document=] is not <a>allowed to use</a> the | ||
"[=web-share-feature|web-share=]" permission, return false. | ||
</li> | ||
<li>Let |base| be [=this=]'s [=relevant settings object=]'s | ||
[=environment settings object/API base URL=]. | ||
</li> | ||
<li>Return the result of [=validate share data=] with |data| and | ||
|base|. | ||
</li> | ||
</ol> | ||
</section> | ||
<section> | ||
<h3> | ||
`canShare(name, options)` method | ||
</h3> | ||
<aside class="note" title="When to use canShare(name, options)"> | ||
<p> | ||
The `canShare(name, options)` method allows developer to check if | ||
a particular member is [=supported=]. Further, through the | ||
`options` method, it allows a developer check if, for example, | ||
the user agent [=supported|supports=] sharing files of a | ||
particular [=MIME type=]. | ||
</p> | ||
<pre class="example"> | ||
// Check if files are supported | ||
if (navigates.canShare("files")) { | ||
// Enable file sharing... | ||
} | ||
|
||
// Alternatively, check if can share jpeg files | ||
if (navigates.canShare("files", { type: "image/jpeg" })) { | ||
// Enable jpeg image sharing... | ||
} | ||
</pre> | ||
</aside> | ||
<p> | ||
When the <dfn data-lt="canShare!overload-1">canShare(name, | ||
options)</dfn> method is called with arguments {{DOMString}} | ||
|name:DOMString| and {{CanShareQuery}} |options:CanShareQuery|, run | ||
the following steps: | ||
</p> | ||
<ol class="algorithm"> | ||
<li>If the [=current settings object=]'s [=environment settings | ||
object/responsible document=] is not <a>allowed to use</a> the | ||
"[=web-share-feature|web-share=]" permission, return false. | ||
</li> | ||
<li>If |name| is "url", return either `true` or `false` depending | ||
on if sharing URLs is [=supported=]. | ||
</li> | ||
<li>If |name| is "text", return either `true` or `false` depending | ||
on if sharing text is [=supported=]. | ||
</li> | ||
<li>If |name| is "files": | ||
<ol> | ||
<li>If sharing files is not [=supported=], return `false`. | ||
</li> | ||
<li>If |options| is doesn't have a {{CanShareQuery/type}} | ||
member, return `true`. | ||
</li> | ||
<li>Let |type| be the result of [=parse a MIME type=] with | ||
{{CanShareQuery/type}} as input. | ||
</li> | ||
<li>If |type| is failure, throw a {{TypeError}}. | ||
</li> | ||
<li>Return either `true` or `false` depending on if the user | ||
agent supports sharing the [=MIME type/essence=] of |type|. | ||
</li> | ||
</ol> | ||
</li> | ||
<li>|name| is not a [=supported share member=], return `false`. | ||
</li> | ||
</ol> | ||
</section> | ||
</section> | ||
<section data-dfn-for="ShareData"> | ||
<h3> | ||
|
@@ -281,7 +383,7 @@ <h3> | |
USVString text; | ||
USVString url; | ||
}; | ||
</pre> | ||
</pre> | ||
<p> | ||
The <dfn>ShareData</dfn> dictionary consists of several optional | ||
members: | ||
|
@@ -313,6 +415,10 @@ <h3> | |
A URL string referring to a resource being shared. | ||
</dd> | ||
</dl> | ||
<p> | ||
A member is <dfn>supported</dfn> if the use agent supports sharing | ||
the value of a {{ShareData}} member with [=share targets=]. | ||
</p> | ||
<div class="note"> | ||
These members are {{USVString}} (as opposed to {{DOMString}}) because | ||
they are not allowed to contain surrogate code points. Among other | ||
|
@@ -328,6 +434,114 @@ <h3> | |
an [^a^] element, before being given to the share target. | ||
</div> | ||
</section> | ||
<section> | ||
<h3> | ||
Validate share data | ||
</h3> | ||
<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, return | ||
false. | ||
<div class="issue" data-number="127"></div> | ||
</li> | ||
</ol> | ||
</li> | ||
<li>If |data|'s url member is present: | ||
<ol> | ||
<li>Let |url:URL| be the result of running the [=URL parser=] on | ||
|data|'s url, with |base|, and no encoding override. | ||
</li> | ||
<li>If |url| is failure, return false. | ||
</li> | ||
<li>If |url|'s [=URL/scheme=] is not "http" or "https", return | ||
false. | ||
</li> | ||
</ol> | ||
</li> | ||
<li>Return true. | ||
</li> | ||
</ol> | ||
</section> | ||
<section data-dfn-for="CanShareQuery"> | ||
<h3> | ||
`CanShareQuery` dictionary | ||
</h3> | ||
<pre class="idl"> | ||
dictionary CanShareQuery { | ||
DOMString type; | ||
}; | ||
</pre> | ||
<section> | ||
<h4> | ||
`type` member | ||
</h4> | ||
<p> | ||
The <dfn>type</dfn> member is a [=MIME Type=] that the developer | ||
would like to check support for. | ||
</p> | ||
</section> | ||
</section> | ||
<section data-dfn-for="SupportedShareMember"> | ||
<h3> | ||
Supported share members | ||
</h3> | ||
<p> | ||
The <dfn>supported share members</dfn> provide a means for developers | ||
to check if particular sharing capabilities are supported by the user | ||
agent. They are represented by the following string literals: | ||
</p> | ||
<dl> | ||
<dt> | ||
"<dfn>files</dfn>" | ||
</dt> | ||
<dd> | ||
Represents support for the {{ShareData/files}} member. | ||
</dd> | ||
<dt> | ||
"<dfn>url</dfn>" | ||
</dt> | ||
<dd> | ||
Represents support for the {{ShareData/url}} member. | ||
</dd> | ||
<dt> | ||
"<dfn>text</dfn>" | ||
</dt> | ||
<dd> | ||
Represents support for the {{ShareData/text}} member. | ||
</dd> | ||
</dl> | ||
<p class="Note" title="Why not an enum?"> | ||
The choice to use string literals instead of an [=enumeration=] is | ||
deliberate. Doing so allows implementers to gracefully support future | ||
{{ShareData}} member values, while also giving the user agent the | ||
ability to disable sharing those members if needed. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this mention whatwg/webidl#893 or whatwg/webidl#491? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. If something changes in WebIDL, then it should be adopted. whatwg/webidl#491 should be closed anyway - it's no longer relevant. |
||
</p> | ||
</section> | ||
</section> | ||
<section> | ||
<h2> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be marked as historical if we think this is a broken approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only if we are not going to ship an alternative - but I don't think anyone plans to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are going to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, yes... there is no plans for any engine to ship anything different. Let's just ship this and be done for now. If we need a new method, we can add it when there is demand for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think Gecko would want to ship anything proven to be broken as a sole solution 🤔
cc @annevk, context: #108 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's ok, but if we can't shift the other implementers then we need to make a process call here (i.e., Mozilla can "formally object" and we figure it out from there).
We have two engines that already ship
.canShare()
already (and have now for over a year).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it depends on real world usage of canShare.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, that too... however, we (you and I) are kinda limited in that we can't actually get that data.
We are at an impasse here :( without input from other implementers willing to change (or even respond to issues), I don't know what we can do 😭
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://chromestatus.com/metrics/feature/timeline/popularity/2737