Skip to content

Introduce canShareFiles #184

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

Closed
wants to merge 2 commits into from
Closed

Conversation

ewilligers
Copy link
Collaborator

@ewilligers ewilligers commented Sep 24, 2020

Note: I am not sure of the best way to word the definition.

This is an incomplete early draft seeking feedback.

For normative changes, the following tasks have been completed:

  • Modified Web platform tests (link to pull request)

Implementation commitment:


Preview | Diff

Note: I am not sure of the best way to word the definition.

This is an incomplete early draft seeking feedback.
@@ -103,15 +103,21 @@ <h3>
</h3>
<pre class="idl">
partial interface Navigator {
[SecureContext] boolean canShareFiles(sequence&lt;USVString&gt; file_types);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I don't see much advantage of allowing a sequence. As this is a synchronous check, it's better to only allow a single value. Then there is no ambiguity about which passed value is supported and which is not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should generalize the name too... to canShareType()

Comment on lines +150 to +152
Each user agent should have an `allowlist` of permitted MIME types
and file extensions or file names. These may contain wildcards, for
example `*.txt` or `text/*`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should only support mime types, not file extensions.

I'd be against using wildcards in the manner suggested here. Let's just stick to well-formed/valid MIME Types per:
https://mimesniff.spec.whatwg.org

Additionally, we should have a list of allowed types that we all agree on, otherwise this API has the potential to becomes a fingerprinting vector.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this needs more details, also for web developers who should have some assurances about the capabilities.

<li>If a file type is being blocked due to security considerations,
return <a>a promise rejected with</a> with a {{"NotAllowedError"}}
{{DOMException}}.
<li>If |data|'s {{ShareData/files}} member is present and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The support check should be split out into its own algorithm (see #177).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note here, we need to do the same check as in #177 to make sure {files: []} gets rejected, but passing {text: "hi", files: []} is ok.

argument |file_types|, run the following steps:
</p>
<ol class="algorithm">
<li>For each |file_type| in |file_types|, if |file_type| does not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want a permissions policy check here. If not allowed, throw NotAllowedError.

<li>If |data|'s {{ShareData/files}} member is present and
{{Navigator/canShareFiles()}} returns false when called with the
files' extensions and content types, return <a>a promise rejected
with</a> with a {{"NotAllowedError"}} {{DOMException}}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a {{TypeError}} instead, as the type is not allowed to be shared.

@marcoscaceres
Copy link
Member

Thanks for putting this together @ericwilligers! This is a really good starting point.

</p>
<ol class="algorithm">
<li>For each |file_type| in |file_types|, if |file_type| does not
match any entry in the user agent's `allowlist`, return `false`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the mime types, they need to be parsed (which can return "failure", so throw a TypeError), and then the "essence" of each type can be checked against the allowlist.

@@ -103,15 +103,21 @@ <h3>
</h3>
<pre class="idl">
partial interface Navigator {
[SecureContext] boolean canShareFiles(sequence&lt;USVString&gt; file_types);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably just want a regular DOMString.

Suggested change
[SecureContext] boolean canShareFiles(sequence&lt;USVString&gt; file_types);
[SecureContext] boolean canShareFiles(sequence&lt;DOMString&gt; file_types);

{{DOMException}}.
<li>If |data|'s {{ShareData/files}} member is present and
{{Navigator/canShareFiles()}} returns false when called with the
files' extensions and content types, return <a>a promise rejected
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: This needs to be spec'ed as a for each |file:File| in files:, the check each file's content type separately.

@marcoscaceres
Copy link
Member

Prototype implementation in Gecko using .canShareType():

Screen Shot 2020-09-28 at 1 36 52 pm

I like it :)

@mgiuca
Copy link
Collaborator

mgiuca commented Oct 27, 2020

Discussed at TPAC 2020. @NotWoods suggests that we do something like this but call it canShare and take a string parameter. Details to follow (see IRC).

@NotWoods
Copy link
Member

We discussed canShareFiles and TAG concerns about adding many methods to the Navigator namespace. If future share categories arise in the future (i.e.: formatted text, html) we would want a canShareX for each which is not ideal.

A design we settled on is to change canShare to take two parameters, a category and optional extra data to refine the check as the second parameter.

partial interface Navigator {
  boolean canShare(ShareCategory category, optional any option);
};

enum ShareCategory {
  "files"
}

The type of the second parameter would change based on the first argument, similar to eventTarget.addEventListener. In the case of "files", it would correspond to the file_type parameter in this proposal.

// check if file sharing is supported
if (navigator.canShare("files") { ... }

// check if image sharing is supported
if (navigator.canShare("files", "image/*") { ... }

@marcoscaceres
Copy link
Member

Re: optional any option);, I'd prefer we use a dictionary there. Then we can have the types: specifically defined there: sequence<DOMString> types;.

@marcoscaceres
Copy link
Member

Actually, playing around a bit... just DOMString type; might be more useful than sequence types;.... otherwise, we get back into the situation where you need to test arrays with a single item to work out what is actually supported.

@marcoscaceres
Copy link
Member

I've updated #177 to specify canShare(name, options)... for backwards compat, what we might be able to do is support both:

            [SecureContext]
            boolean canShare(optional ShareData data = {});

            [SecureContext]
            boolean canShare(DOMString name, optional CanShareQuery options = {});    

Then we can just encourage developers to use the canShare(name, options) version when it's widely supported.

Let me know what you think...

@NotWoods
Copy link
Member

Can we simply leave the previous version as a Chromium-only variant rather than including it in the spec?

@marcoscaceres
Copy link
Member

Can we simply leave the previous version as a Chromium-only variant rather than including it in the spec?

We can, but that might end up having web compat issues (for Gecko)... I guess it somewhat depends on what the Webkit folks want to do also. Safari shipped with canShare() matching Chrome, I believe.

The above allows us to move away from the original version in somewhat sane way without breaking too much content (although the usage stats suggest that usage of .canShare() is low still).

cc @othermaciej

Base automatically changed from master to main February 3, 2021 03:22
@marcoscaceres
Copy link
Member

Closing, as we not implemented by anyone. Looks like we are sticking with .canShare().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants