DOM implementation of Web Share API
Categories
(Core :: DOM: Core & HTML, enhancement, P1)
Tracking
()
People
(Reporter: jkt, Assigned: marcosc)
References
()
Details
(4 keywords, Whiteboard: [geckoview:m1909] [geckoview:m1910], [wptsync upstream])
Attachments
(2 files, 2 obsolete files)
Updated•8 years ago
|
Assignee | ||
Updated•8 years ago
|
Assignee | ||
Updated•8 years ago
|
Assignee | ||
Comment 1•8 years ago
|
||
Updated•8 years ago
|
Comment 2•8 years ago
|
||
Reporter | ||
Comment 3•8 years ago
|
||
Comment 4•8 years ago
|
||
Updated•8 years ago
|
Assignee | ||
Comment 7•7 years ago
|
||
Comment 8•7 years ago
|
||
Assignee | ||
Comment 9•7 years ago
|
||
Comment 10•6 years ago
|
||
Comment 11•6 years ago
|
||
It looks like it's coming to iOS soon.
https://www.reddit.com/r/iOSBeta/comments/ak29s1/feature_website_sharing_using_js_feature_now/
Updated•6 years ago
|
Updated•6 years ago
|
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Comment 12•5 years ago
|
||
Initial DOM implementation
Assignee | ||
Comment 13•5 years ago
|
||
@olli, @baku, in order to create something like in the screenshot above on Desktop, but also allow share to work on Android/Fenix as a modal dialog, I was thinking of replicating how context menus are implemented in Gecko (I don't actually know how Context Menus are implemented... hence me pinging you here for guidance - so loosely basing this off nsContextMenu.js [1] ).
Here a is a rough sketch of what I'm thinking architecturally... The IDL would be:
// https://wicg.github.io/web-share/#navigator-interface
partial interface Navigator {
[SecureContext, Throws] Promise<void> share(optional ShareData data = {});
};
// https://wicg.github.io/web-share/#sharedata-dictionary
dictionary ShareData {
USVString title;
USVString text;
USVString url;
};
// The following events are fired internally inside Navigator::Share()...
[ChromeOnly, Constructor(optional MozShareEventInit eventInit = {})]
interface MozCanShareEvent : Event {
void supportsSharing(ShareResponse canShare);
};
[ChromeOnly, Constructor(optional MozShareEventInit eventInit = {})]
interface MozWebShare : Event {
readonly attribute USVString title;
readonly attribute USVString text;
readonly attribute USVString url;
void shareResult(ShareResponse didShare); // Called second
};
dictionary MozShareEventInit : EventInit {
USVString title;
USVString text;
USVString url;
};
enum ShareResponse { "success", "fail", "abort" };
So, effectively, when Navigator::Share(ShareData data)
is called, we do various pre-checks (e.g., check the url member is a valid url, etc.), and a promise mSharePromise
is returned to script. Then, in order to handle the async aspects:
- Fire a
MozCanShareEvent
: this would allow GeckoViewPrompt.js and the equivalent on desktop to listen for a "canshare" event (can we prevent this from going to the actual Document... I only want GeckoViewPrompt.js to pick it up?). - If it has any registered "share targets" on Android or Desktop, it calls
ev.supportsSharing("success")
. Otherwise, "fail" -mSharePromise
is rejected with someDOMException
. - If "yes",
::Share()
then dispatches a"share"
event. - GeckoViewPrompt.js listens for the event and tries to do the sharing: In JS/Android, show the actual context menu (do something similar to nsContextMenu.j [1] for Desktop... at mouseX, mouseY, etc.).
- Depending on the outcome of doing the share on Android or Desktop, the script calls
ev.shareResult(/*a ShareResponse value, like "abort" if the user aborted*/)
. - Either ::Share() gets the above call back, or we have a
PromiseNativeHandler
pick this up somehow. mSharePromise
is settled: either resolve, or rejected.
WDYT? Some better way to do this? I'm open to alternatives.
[1] https://searchfox.org/mozilla-central/source/browser/base/content/nsContextMenu.js#115
Comment 14•5 years ago
|
||
It seems a good plan. I would like to know from Gijs if we can reuse some existing code from nsContextMenu.
Comment 15•5 years ago
|
||
(In reply to Andrea Marchesini [:baku] from comment #14)
It seems a good plan. I would like to know from Gijs if we can reuse some existing code from nsContextMenu.
I'm afraid I don't understand the question. We don't have a context menu share implementation. What kind of code do you want to reuse?
Comment 16•5 years ago
|
||
I'm thinking about how to open the contextual menu in the right position. Is it something that can be shared between this new 'shared' context menu and the right-click one?
Comment 17•5 years ago
|
||
(In reply to Andrea Marchesini [:baku] from comment #16)
I'm thinking about how to open the contextual menu in the right position. Is it something that can be shared between this new 'shared' context menu and the right-click one?
There's not really a lot to be shared. We just pass a screenX/screenY from the content process to the parent, see https://searchfox.org/mozilla-central/rev/da3f3eaaacb6fb344fd21ac29ace2da0e33f12d3/browser/base/content/nsContextMenu.js#122-123,135 (parent) and https://searchfox.org/mozilla-central/rev/da3f3eaaacb6fb344fd21ac29ace2da0e33f12d3/browser/actors/ContextMenuChild.jsm#749-750 (child)
Comment 18•5 years ago
|
||
So, effectively, when
Navigator::Share(ShareData data)
is called, we do various pre-checks (e.g., check the url member is a valid url, etc.), and a promisemSharePromise
is returned to script. Then, in order to handle the async aspects:
- Fire a
MozCanShareEvent
: this would allow GeckoViewPrompt.js and the equivalent on desktop to listen for a "canshare" event (can we prevent this from going to the actual Document... I only want GeckoViewPrompt.js to pick it up?).- If it has any registered "share targets" on Android or Desktop, it calls
ev.supportsSharing("success")
. Otherwise, "fail" -mSharePromise
is rejected with someDOMException
.
event dispatch is synchronous, but sharing support needs to happen asynchronously in the parent process (right?).
Couldn't you just add a new (async) message to PContent which returns the result?
- If "yes",
::Share()
then dispatches a"share"
event.- GeckoViewPrompt.js listens for the event and tries to do the sharing: In JS/Android, show the actual context menu (do something similar to nsContextMenu.j [1] for Desktop... at mouseX, mouseY, etc.).
- Depending on the outcome of doing the share on Android or Desktop, the script calls
ev.shareResult(/*a ShareResponse value, like "abort" if the user aborted*/)
.
How does this work, given that DOM event dispatch is synchronous, and message passing from child to parent is asynchronous?
Comment 19•5 years ago
|
||
Adding [geckoview:fenix:m8]
whiteboard tag because we would like to implement Web Share for GeckoView and Fenix (bug 1402369) in Q3.
Assignee | ||
Comment 20•5 years ago
|
||
(In reply to :Gijs (he/him) from comment #17)
(In reply to Andrea Marchesini [:baku] from comment #16)
I'm thinking about how to open the contextual menu in the right position. Is it something that can be shared between this new 'shared' context menu and the right-click one?
There's not really a lot to be shared. We just pass a screenX/screenY from the content process to the parent, see https://searchfox.org/mozilla-central/rev/da3f3eaaacb6fb344fd21ac29ace2da0e33f12d3/browser/base/content/nsContextMenu.js#122-123,135 (parent) and https://searchfox.org/mozilla-central/rev/da3f3eaaacb6fb344fd21ac29ace2da0e33f12d3/browser/actors/ContextMenuChild.jsm#749-750 (child)
Ok, so, it might be neat then to create a "ShareMenuChild.js", "ShareMenuParent.js". At least, conceptually, they should be mostly structurally the same as context menu, but we can build independent share menu. We can then build that up over time using the ContextMenu implementation as inspiration/guide.
(In reply to Olli Pettay [:smaug] from comment #18)
How does this work, given that DOM event dispatch is synchronous, and message passing from child to parent is asynchronous?
I was looking at how FullScreen API works... it does: nsContentUtils::DispatchEventOnlyToChrome(), which gets picked up by the child:
https://searchfox.org/mozilla-central/source/browser/actors/DOMFullscreenChild.jsm#46
I can then pick that up ShareMenuChild.js -> which can send the message up to the parent.
GeckoView could also use the same thing:
https://searchfox.org/mozilla-central/source/mobile/android/chrome/geckoview/GeckoViewContentChild.js#409
However, I need to get a callback from the parent to the child to let me know two things: is share supported, and did the share succeed.
So:
- Hey, child, ask the parent/OS if it actually supports sharing?
- Wait for response: If yes, continue. If no, reject
mSharePromise
, with AbortError. - Hey child, tell parent to share this { data } and let me know how it goes.
- Wait for response: how did the share go? "success", "failure", (user) "aborted" - settle mSharePromise appropriately.
From c++, is there some way I can set up a callback to listen for messages as described above?
Comment 21•5 years ago
|
||
What's the current status of this issue :marcosc? This is the last remaining piece left for PWA support in Fenix.
Assignee | ||
Comment 22•5 years ago
|
||
Coming along, but waiting on feedback. I’d guess another 2-4 weeks to stabilize it. However, we can do Geckoview side in parallel. We have a pretty good idea how it’s going to work.
Assignee | ||
Comment 23•5 years ago
|
||
@baku, @saschanaz and I have been putting in the IPC infrastructure and I'm now able to successfully send messages back and forth over IPC (yay!). We are wondering if you can provide us some feedback on the basic design of the IPDL protocol and how it's been implemented?
See: https://phabricator.services.mozilla.com/D36714
However, we have no idea how to now send a message to get a message to GeckoViewPrompt.js ... Basically, we are stuck at:
WebShareParent::RecvHasShareTargets() -> {🤷♂️ no idea/magic 🤷♀️} -> GeckoViewPrompt.js
Any suggestions? Or anyone we could ping for help?
Comment 24•5 years ago
|
||
I wrote some comments about the IPDL, but all good. About GeckoView, usually I ask for help to :esawin, who is on PTO.
Assignee | ||
Comment 25•5 years ago
|
||
Ok, I'm just going to copy ColorPicker for now. The architecture closely resembles what we want for Web Share IMO.
Updated•5 years ago
|
Assignee | ||
Comment 26•5 years ago
|
||
Working though it with folks from the DOM Team... hope to have something in a couple of weeks.
Assignee | ||
Comment 27•5 years ago
|
||
The IPC stuff, for discussion.
Updated•5 years ago
|
Comment 28•5 years ago
|
||
Changing whiteboard tag to [geckoview:m1909]
because Emily expects WebShare will land in September.
Assignee | ||
Comment 29•5 years ago
|
||
Web Share base implementation
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Assignee | ||
Comment 30•5 years ago
|
||
Hi Nika,
I'm getting this odd build error on Try [1], but not on my local compile:
/builds/worker/workspace/build/src/dom/ipc/WindowGlobalParent.cpp:320:55: error: Type 'mozilla::dom::WindowGlobalParent::ShareResolver' (aka 'function<void (const nsresult &)>') must not be used as parameter
Which I assume has something to do with https://bugzilla.mozilla.org/show_bug.cgi?format=default&id=1339537 ?
Any suggestions on how to fix that?
Comment 31•5 years ago
|
||
(In reply to Marcos Caceres [:marcosc] from comment #30)
Hi Nika,
I'm getting this odd build error on Try [1], but not on my local compile:/builds/worker/workspace/build/src/dom/ipc/WindowGlobalParent.cpp:320:55: error: Type 'mozilla::dom::WindowGlobalParent::ShareResolver' (aka 'function<void (const nsresult &)>') must not be used as parameter
Which I assume has something to do with https://bugzilla.mozilla.org/show_bug.cgi?format=default&id=1339537 ?
Any suggestions on how to fix that?
You can't pass std::function
directly as a parameter unfortunately. IIRC the Mac OS STL uses an alignas
declaration somewhere in the implementation, which has ABI issues potentially leading to unaligned loads on x86, leading to the MOZ_NON_PARAM warning.
The easiest solution is to pass the function in by reference, as-in std::function<foo>&&
. In this case you'd want to probably take ShareResolver&&
. Ideally this won't be required forever, as this current restriction is unfortunate.
Comment 32•5 years ago
|
||
Emily recommends we move GeckoView Web Share (bug 1402369) out of GeckoView's September sprint and back to the top of our October backlog. GV work is still blocked waiting for this DOM Web Share bug.
Comment 33•5 years ago
|
||
Tentatively adding to GeckoView's October sprint.
Assignee | ||
Comment 35•5 years ago
|
||
All feedback has been addressed. Just waiting on ✅ so we can finally land this! 🎉
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Comment 36•5 years ago
|
||
Matching Bug 1402369 with P1.
Comment 37•5 years ago
|
||
Setting firefox70=wontfix because we don't need to uplift the Web Share API to GeckoView 70 Beta.
Comment 38•5 years ago
|
||
Comment 41•5 years ago
|
||
bugherder |
Comment 43•5 years ago
|
||
I've done some docs updates on this; see https://github.com/mdn/sprints/issues/2271#issuecomment-554352178 for the full details. Let me know if you'd like to see anything else done at this current time. Thanks!
Comment 44•3 years ago
|
||
Is there a followup bugzilla issue I can track that will move closer to this Web Share API demo working in Firefox on MacOS?
https://web-share.glitch.me/
Thanks!
I doubt there is, you can file one 👍
Description
•