w3c / web-share Goto Github PK
View Code? Open in Web Editor NEWWeb API proposal for sharing data from a web page
Home Page: https://www.w3.org/TR/web-share/
License: Other
Web API proposal for sharing data from a web page
Home Page: https://www.w3.org/TR/web-share/
License: Other
In #7 I proposed sharing Blobs. The primary use case for this is sharing images, but using this API to share images is a bit hard. If you wanted to share the contents of a <canvas>
you would do:
var canvas; // HTMLCanvasElement representing a <canvas> element
canvas.toBlob(blob => navigator.share({blob: blob, mimeType: 'image/png'}),
'image/png');
A little unwieldy, but manageable.
To share an <img>
element, things get a bit hairy:
var image; // HTMLImageElement representing an <img> element
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext('2d').drawImage(image, 0, 0);
canvas.toBlob(blob => navigator.share({blob: blob, mimeType: 'image/png'}),
'image/png');
(Note: I haven't tested this code, just wrote it on the fly. There may be an easier way but that's the best way I can find to convert an image into a blob.)
So maybe we should be providing a share attribute called 'image'
that takes a CanvasImageSource -- basically lets you directly share an Image, Video or Canvas object without having to convert to a blob. The usage would be:
var image; // HTMLImageElement representing an <img> element
navigator.share({image: image, mimeType: 'image/png'}),
As shown above, this isn't strictly necessary (can be polyfilled). So it would be a policy decision whether we want to provide unnecessary-but-helpful abstractions, or whether we should save that for wrapper libraries.
Having something like:
partial interface Navigator {
boolean canShare();
};
Would probably need to be async. The problems is:
Otherwise, the UA would need to do IPC to check if there are handlers available - so basically that's a nonstarter there, or am I missing something?
As the spec already declares [SecureContext] in the IDL, this doesn't need to be stated:
Due to the capabilities of the API surface, navigator.share is available only in secure contexts (such as https:// schemes).
Using WebShare returns an error: "Uncaught (in promise) DOMException: Internal error: could not connect to Web Share interface.".
The test device I'm using is running Android 7.0 and I'm using the Chrome Beta(Chrome 62) as WebView Implementation. Web Share works fine on Chrome Beta application.
E.g. "The Navigator interface is defined in [HTML].", but clicking on the "HTML" link goes nowhere. The bibliography appears to be missing.
This may be related to some kind of broken build process which is also producing some escaped HTML at the top of the document:
<p><a href="https://www.w3.org/" class="logo"> <span id=""> <img alt="W3C" src="https://www.w3.org/StyleSheets/TR/2016/logos/W3C" height="72" width="48"> </span></a></p>
The following call:
navigator.share({foo: 'xyz'})
Currently results in a successful share with no data.
It should reject with a TypeError
.
Rationale: Empty shares are a bad user experience. They show up in the target application as empty strings which is confusing. There's the simple case of passing an empty dictionary to share
, but we also have to consider the more plausible case of adding new fields in the future, and how sites that use the new API will interact with old UAs that don't support those new fields.
The current status quo is that if you share only new fields, you'll share nothing on an old UA.
We should offer feature detection for these new fields (see WebIDL #107) and then make it a TypeError if you fail to properly use the feature detection and only share new fields.
This is related to #47 which is about making navigator.share()
equivalent to navigator.share({})
. If we make this change, navigator.share()
would remain a TypeError which makes me happy. I think navigator.share()
being a successful share is nonsensical.
Consider the situation:
function declaredInWindow3() {
window1.navigator.share.call(window2.navigator, { url });
}
Then navigate the frame containing window3 to window4, but save a reference to declaredInWindow3
. Finally, from code in window5, call the saved function.
Which of these five documents does url
get resolved relative to?
The proper pattern for this is to parse against
this Navigator object
's relevant settings object's API base URL
in which case the answer will be window2.
Currently if you do navigator.share()
on https://example.com/
, it will share https://example.com/undefined
, by my reading. (I.e. it will convert undefined
to a USVString
, then resolve it as a relative URL.)
If you add a default to the dictionary of url = ""
, it will instead share the current page URL, which seems nice.
There should be a way to share large blobs / files using the Web Share API.
Couple of ways to do this:
blob
or file
attribute to the share data object, allowing such objects to be added directly.url
attribute to a Blob URL to reference a blob.The latter approach is nice because it keeps the API surface small and forces you to share just one piece of content (either a web URL or a Blob URL, but not both). This may or may not be desirable.
The spec talks for "fields" throughout, but in IDL these are called members.
https://heycam.github.io/webidl/#dfn-dictionary-member
We probably want to be constant in case "fields" end up in WebIDL with a different meaning.
@marcoscaceres indicated that we would need text language and direction attributes for shared text.
This seems like overkill to me, as we're essentially just sharing plain text. I'm not sure why language is required, and directionality should be inferrable from the text (in the standard way, by looking at the first strong character, and if the client really wants to override it, they can add a U+200F RLM). Do you have an example of an existing W3C standard that has out-of-band language and direction attributes for plain text?
I found the Notifications spec which has an explicit direction attribute. It seems there is a single direction that controls the entire notification UI ("auto", "ltr" or "rtl"), affecting all text fields (title, text, etc) as well as the layout of the buttons. It seems like that's useful for giving the site control over the precise layout of the notification (since the notification forms part of the site's UI). That doesn't make a lot of sense for Web Share because the sending site is not presenting any form of UI; rather it is sending text and other data to a different app. It's not clear what an explicit "ltr" or "rtl" should mean in the context of the receiving app. (For example, what is Twitter supposed to do if it receives an all-English text string with dir="rtl"?)
Why not add a rel-share to this spec.?
See here: http://microformats.org/wiki/sharelink-examples
So we end up with this:
<a role="link" rel="share" href="https://www.example.com/share?title={title}&text={text}&url={url}">Share This</a>
An update to Approach 1 found here: https://github.com/WICG/web-share-target/blob/master/docs/interface.md#approach-1-1
Just an idea?
I'm not a huge fan of "Extensibility of the API" section, tbh. I don't think we should include it: The Share API is not any more special wrt extensibility than any other API. Same extensibility rules apply to platform APIs.
The following feedback was emailed to me so passing on here:
I'm actually working on a collaborative whiteboard application. I wanted to share the drawings on the canvas as an image. I generated the image and tried to share it using such a code:
let url = canvasElement.toDataURL('image/png');
navigator.share({
title: document.title,
text: "Shared whiteboard",
url: url
}).then(() => console.log('Successful share'))
.catch(error => console.log('Error sharing:', error));However, I got an exception:
"Error sharing: DOMException: Must be handling a user gesture to perform a share request."I would say this was quite unexpected, because I was clicking on a button in the same way as with the sharing of a regular URL. I'm not sure why this user gesture was not accepted.
Moreover, is sharing of images in such a way supported?
Current behaviour in Chrome (intentional) that wasn't captured in the spec: the "url
" field can be a relative URL, and if it is, it is converted into an absolute URL based on the current location, in the same way as relative URLs in links are.
In particular, sharing a URL of '.'
shares the current page location's directory (without the final path segment); sharing a URL of ''
shares the current URL.
The example states "Share successful"... but that's not quite correct. What was successful there was just the handoff of the data, but not necessarily that the sharing actually happened.... I know, I'm nit picking a bit here, but we don't want to mislead people into thinking the API is doing more than it actually does.
This specification has been proposed for migration to the WebApps WG (which is expected to partly replace the WebPlat WG). For this to happen, we need expressions of interest/intent to commit from at least two implementors.
Please let us know if you plan to implement this specification, or if you can point to any publicly documented expressions of interest from implementors.
The draft WebApps charter will go to the Advisory Committee (AC) within the next two or three weeks, so quick responses may make the difference.
If navigator.share
is used on a web page that was written on April 1, the User Agent should display a warning to the user, with this text or similar:
"Warning: You are sharing content that may contain false information or fake news. Are you sure you want to spread this content?"
...if you feel like changing it, I'd argue that user gesture checks are not quite security sensitive, but rather prevent user annoyance. FWIW, https://fullscreen.spec.whatwg.org/ rejects with TypeError.
@sammc I think we borrowed the SecurityError from some other API, so there may be two different precedents. Do you remember which?
As discussed with @marcoscaceres yesterday, the canShare
method may be unnecessary.
Since it provides no actual arguments to query exactly what actions are supported, and any implementation of Web Share is likely to have at least one default action, it's likely that canShare
would simply always return true in any implementation. Therefore, people would not check it and it would probably break sites if a rare implementation returned false. So we might just drop it (and sites can use the presence of navigator.share
itself to detect whether sharing is supported).
On the other hand, if we are going to share more interesting types of data (like files, images, etc), there may be different sets of apps that can handle these data types, and we may want canShare
to take an argument that describes the data, to see if there is an app that can handle that particular type.
A page defines an offer or organisation in a micro format like json+ld or so. The example should explain how this would work with the share api
It seems like the section should just be marked normative
https://github.com/WICG/web-share/blob/master/docs/interface.md
dictionary ShareData {
DOMString? title;
DOMString? text;
DOMString? url;
};
Most dictionary members of DOMString type are not nullable. If there is no title, {}
and { title: undefined }
would both be syntaxes for specifying this.
If it is not possible from URL, is there any method to convert a URL of image/video to a filelist object?
In Bikeshed, most of this should be a simple matter of e.g. doing [=in parallel=]
instead of in parallel
.
WebShare currently allows developers to share content, but it would also define a mechanism for Web applications to become share targets and so, leverage PWA by closing another gap between native and web apps. It is of particular importance for social web applications.
(Just reading through the docs and filing issues as things come to mind... not fully formed ideas or anything, and probably already have good answers to any questions)
It would be great if the explainer could also discuss pros/cons of a declarative solution. For example:
<img src="https://example.com/cat" sharable>
Or:
<article sharable>
</article>
And perhaps how the API could be used in conjunction with Web Components?
Raised by @dbaron on the TAG review.
There is a minor privacy issue in distinguishing between "no apps are available" and "the user cancelled the share"; if only a handful of popular targets exist for a particular payload (especially if we add new share types that might have specialized handlers, e.g., for rare MIME types) then a malicious site could use navigator.share
to check whether those apps are installed, based on the response string.
Also, in our current Android implementation, we are totally unable to distinguish between "no apps are available" and "the user cancelled the share". Therefore, let's just remove this provision. I won't go as far as to explicitly bar the user agent from distinguishing these, but add a note under security considerations.
FR from Discourse: https://discourse.wicg.io/t/web-share-api-for-sharing-content-to-arbitrary-destination/1561/10
The developer wants a way to automatically insert a query parameter onto the shared URL like "utm_source=$TARGET_APP
", which would identify which app the user chose to share to, so that the sending app can gather metrics about where their incoming links are coming from. For example:
navigator.share
with `url: 'https://example.com``.utm_source=facebook
into the URL.This is a bit worrying from a privacy perspective -- the sender is not supposed to know which app the user chose to share to. But this is a lot more indirect because the sender only gets info about the shared app once the friend clicks the link in Step 6, so there's nothing to directly tie the app to the user. Will have to think on this.
This isn't something I'd want to do automatically. I'd want the sender to be able to opt in by adding a new data field to ShareData
, e.g., add_target_to_url: 'utm_source'
.
My final concern is that we don't have a good scheme to name the target app. I suppose if it's a Web Share Target it would be the full URL to the app's manifest scope. If it's an Android app, it would be the Android package name, etc. So we wouldn't get something as clean as "facebook"; it would be more like "com.facebook.katana" (the Android app). It's also a bit messy because it would be the name of the app the user shared to, not the name of the app the friend clicked the link in (so if the user shared to the Android app, but the friend clicked the link on the web, the utm_source
would still show the Android app package name). This all seems very messy.
We received a lot of requests from the Chrome Origin Trial for Web Share for improving the documentation.
Aside from writing a proper spec, we should get some dedicated developer docs (possibly coordinating with MDN).
Since these are being passed to other systems, blob URLs might not make sense there.
On the other hand, maybe they would, e.g. when web share targets are available. So maybe this is fine. But I wanted to raise the possibility.
Presumably navigator.share(...)
will show some modal UI. Should this be gated behind a user gesture, or are there use cases where the user isn't interacting with the page and would still be able to understand why a share UI is being presented?
A consequence of requiring a user gesture would be that the API couldn't be exposed in workers.
Spec says:
User agents that do not support sharing SHOULD NOT expose share on the Navigator interface.
This doesn't seem great. A share target can be removed/added, etc. making this super weird if the API vanishes from one page load to the next.
What we should have a is static method a on Navigator, or just normal method even, as navigator is just a singleton:
if(await navigator.canShare()){
await navigator.share(stuff);
}
In a number of places, the spec says that .share()
"throws"... although exceptions are auto-wrapped, and .share()
's promise will be rejected, saying "throws" might confuse people expecting the method to actually throw.
We should consistently say that .share()
will return a rejected promise instead.
Hi team-
Would it be possible to comment on or document how the share targets selection of the Web Share API is currently planned and what a roadmap might be for more native-like coverage?
Currently, if I use the demo via Chrome 75 on Android 9 to share an image or video file, common 3rd-party targets for these file types (e.g., Instagram, Twitter) don't show up in the share sheet. If I try to share it directly from the (native) Camera app, they do as expected.
The current wording in the spec is:
Present the user with a choice of one or more share targets, 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.
Is the current level of discretion intended to change in future implementations? I realize this question may be better for the Chromium/Chrome team - it's a little unclear to me what is spec and what is implementation at this point.
The Web Share API (and other web app technologies introduced at I/O19) is super promising, but it's unclear how best to understand these differences and the impact they have on 'thin native app' vs. PWA design.
Thanks for considering!
Some user agents may wish to prevent certain file types, for example executable files, from being shared. This decision might be made on the basis of MIME type or file extension, and the platform.
For example, Blink identifies various file extensions as dangerous: download_file_types.
Some user agents may wish to prevent certain sites from sharing, for example known phishing sites.
Should script be able to detect in advance that such share attempts will fail? If so, then share
should throw a TypeError
and canShare
should return false
. If not, then share
should throw a NotAllowedError
(like if there was no user gesture) or AbortError
(like if the user cancelled or there were no suitable share targets) and canShare
should return true
.
Hi Folks working on this... with the Web Apps WG now up and running, we are ready to adopt this specification into the WG for formal standardization along the w3c rec track. π
Before doing so, I could use a bit of help just filling out the template below... I've got things started already, but those with knowledge of the spec please jump in.
In W3C WebApps Charter
https://github.com/WICG/web-share/
Adopt level/version 1 and 2?
An API for sharing text, links and other content to an arbitrary destination of the user's choice.
The available share targets are not specified here; they are provided by the user agent. They could, for example, be apps, websites or contacts.
Described in the explainer.
Please characterize how much we might regret standardizing this new feature were we to change or remove it in the future. If you donβt have a github repository, include in this email links to relevant discussions, or documentation about support for the feature on the Web.
As the feature is shipping in two browsers, there is risk with making too many changes to v1 of this API. However, it would be good to perform conformance/interop testing, and address any issues during the next phase of the standardization process.
Discussion of options on various operating systems:
https://github.com/WICG/web-share/blob/master/docs/native.md
Not supported as a native feature across all operating systems. It is foreseeable that browsers could "share" across web apps, via the Share Target API.
Implemented in Chrome (since 61) and Safari (since 66).
Was also trialed/used on twitter.com. (still used there?)
What data do you have available that indicates that this enhancement will affect many users of the Web. Quantify the fraction of websites that are currently using something similar to this feature. Or, if a new feature, characterize the reason that you expect this to be far reaching.
Outline the security and privacy implications of your proposal for end-users. Otherwise, indicate if there are none.
Outline the implications of your proposal relative to access by everyone regardless of disability. Otherwise, indicate if there are none.
See issue #6
Heads up that to get to these demos, a search for "web share api test wicg github" on Google results in a link (wicg.github.io/web-share/demos/share-files.html) with http:
scheme. The distinction between http and https is somewhat hidden on mobile still as compared to current desktop browsers.
Per the docs this API only works from https:
. Because I didn't realize that I hadn't loaded https, it took a while to figure out if my browser needed Android-level app permissions for this to work or there was some other failure - more diagnostic if possible while enabling bleeding edge capability is always welcome.
Thanks for considering, and looking forward to using this API!
(Curiously the demo is the only link in these search results that's still on http by default)
In the current spec, Section 2.1.1 step 5.1 instructs the browser "If there are no share targets available, reject p with AbortError, and abort these steps."
I'd like to propose instead that step 5.2 be expanded to allow a UI workflow for adding a new share target to use immediately. In the event a browser has no such UI and no share targets exist, only then should the promise automatically be rejected with an AbortError. This change would also negate the verbiage in Section 2.1 that instructs the browser in regards to feature detection when no share targets are available.
Currently the share
method throws an AbortError
for three distinct failure modes:
Lumping all three of these together (making them indistinguishable to the client) may not be sufficient. Consider an app that wants to use the following logic:
share
.It is not currently possible to distinguish these cases. It seems the most important thing to distinguish is whether it failed before or after the user saw the picker. Secondarily, we might want to distinguish user cancellation and transmission error.
Should we perhaps change to reject with a different error type in each case? Or somehow attach additional data to the rejection object.
Just as heads up that the W3C's automated IPR system added "index.html" to the root of the repo... it also added some other small files that it needs + a web hook.
I may have missed this, but what counts as a "Share successful"?
How about "Failure"?
Has the ramifications of this been thought through for user privacy / control (for want of a better word) - what happens if a website insists you share something before allowing you access to a resource?
This is another thing that's a bit surprising in Web IDL, but if a dictionary has no required members, then when used as an argument type, that argument must be optional. It's this bit from https://heycam.github.io/webidl/#idl-operations:
If the type of an argument is a dictionary type or a union type that has a dictionary as one of its flattened member types, and that dictionary type and its ancestors have no required members, and the argument is either the final argument or is followed only by optional arguments, then the argument must be specified as optional. Such arguments are always considered to have a default value of an empty dictionary, unless otherwise specified.
The reason is that with no required arguments, navigator.share({})
still works, and then it looks "silly" to require the empty object.
The demo code fails to parse in some browsers, leading the entire javascript file to be rejected. Specifically, at https://developers.google.com/web/updates/2016/10/navigator-share, the phrase:
.then(() => console.log('Successful share')) .catch(error => console.log('Error sharing:', error))
Similar code is also used in demos/share.html
and also fails to parse.
It fails in Konqueror 4.14.2 (Debian stable (Jessie 8)). I believe (based on access logs for users who reported problems) it also fails in:
"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_4 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13G35 Safari/601.1"
Bit of a nit... but for .share()
steps, it says:
Activate the chosen share target, convert data to a format suitable for ingestion into the target, and transmit the converted data to the target. If an error occurs starting the target or transmitting the data, reject p with AbortError, and abort these steps.
That might be better classed as TypeError
there, as it's the data that caused the error. I guess the message of the AbortError could still say that... Feel free to ignore.
Hiya! This is a pretty complicated ask, but I'd like to see offline support added to enrich this great capability.
From within a user-agent, if an origin has a foreign-fetch worker installed, other origins can- even while offline- issue requests and the foreign fetch handler has an opportunity to serve that request.
It would be very interesting and powerful if the user-agent could externalize this servicing: when a "Gallery" application goes to open a photo url, if the OS could proxy that request through the user-agent such the user agent could try to use it's foreign-fetch handler, then it could be possible for Gallery to open a photo even though the device is disconnected.
Also, without some kind of integration with foreign fetch, the Gallery app will always have to redownload the image, even though the user agent may have it cached, & that could be a considerably large download.
The note that states:
always shows some form of UI, to give the user a choice of application...
Would probably better to move that to the Security and privacy considerations. Also, the language there seems to overstep a bit into making hard UI requirements.
I suggest softening the language a bit, and make recommendations instead.
The current spec has a provision for the target to "decline to receive the data". Despite this, neither the existing Android implementation on Chrome nor the proposed Web Share Target URL-template-based API would allow the target to respond with a failure state.
Given that we aren't likely to make use of this in the near future, and that it could be re-added in a backwards-compatible way if we wanted to introduce a new failure mode, let's just remove this text from the spec for now.
The two notes in the "ShareData dictionary" section are really not needed (the one about USVString, and the one about url possibly being relative). I'd suggest dropping them.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.