mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-05 05:30:29 +00:00
Bug 1312422 - Web Share Base/DOM implementation r=farre
Web Share base implementation just of DOM stuff - working together with @saschanaz. @Baku, we would greatly appreciate your review. -Nika, as she is traveling. Differential Revision: https://phabricator.services.mozilla.com/D44598 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
ac1ba8670f
commit
fbff2e387c
@ -55,6 +55,7 @@ DIRS += [
|
||||
'uitour',
|
||||
'urlbar',
|
||||
'translation',
|
||||
'webshare',
|
||||
]
|
||||
|
||||
DIRS += ['build']
|
||||
|
55
browser/components/webshare/SharePicker.js
Normal file
55
browser/components/webshare/SharePicker.js
Normal file
@ -0,0 +1,55 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
class SharePicker {
|
||||
constructor() {}
|
||||
|
||||
get classDescription() {
|
||||
return "Web Share Picker";
|
||||
}
|
||||
|
||||
get classID() {
|
||||
return Components.ID("{1201d357-8417-4926-a694-e6408fbedcf8}");
|
||||
}
|
||||
|
||||
get contractID() {
|
||||
return "@mozilla.org/sharepicker;1";
|
||||
}
|
||||
|
||||
get QueryInterface() {
|
||||
return ChromeUtils.generateQI([Ci.nsISharePicker]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The data being shared by the Document.
|
||||
*
|
||||
* @param {String?} title - title of the share
|
||||
* @param {String?} text - text shared
|
||||
* @param {nsIURI?} url - a URI shared
|
||||
*/
|
||||
async share(title, text, url) {
|
||||
// If anything goes wrong, always throw a real DOMException.
|
||||
// e.g., throw new DOMException(someL10nMsg, "AbortError");
|
||||
//
|
||||
// The possible conditions are:
|
||||
// - User cancels or timeout: "AbortError"
|
||||
// - Data error: "DataError"
|
||||
// - Anything else, please file a bug on the spec:
|
||||
// https://github.com/w3c/web-share/issues/
|
||||
//
|
||||
// Returning without throwing is success.
|
||||
//
|
||||
// This mock implementation just rejects - it's just here
|
||||
// as a guide to do actual platform integration.
|
||||
throw new DOMException("Not supported.", "AbortError");
|
||||
}
|
||||
|
||||
__init() {}
|
||||
}
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([SharePicker]);
|
2
browser/components/webshare/SharePicker.manifest
Normal file
2
browser/components/webshare/SharePicker.manifest
Normal file
@ -0,0 +1,2 @@
|
||||
component {1201d357-8417-4926-a694-e6408fbedcf8} SharePicker.js
|
||||
contract @mozilla.org/sharepicker;1 {1201d357-8417-4926-a694-e6408fbedcf8}
|
4
browser/components/webshare/moz.build
Normal file
4
browser/components/webshare/moz.build
Normal file
@ -0,0 +1,4 @@
|
||||
EXTRA_COMPONENTS += [
|
||||
'SharePicker.js',
|
||||
'SharePicker.manifest',
|
||||
]
|
@ -106,6 +106,7 @@
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "mozilla/webgpu/Instance.h"
|
||||
#include "mozilla/dom/WindowGlobalChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -142,6 +143,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator)
|
||||
tmp->Invalidate();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSharePromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
@ -167,6 +169,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRServiceTest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSharePromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator)
|
||||
@ -234,6 +237,8 @@ void Navigator::Invalidate() {
|
||||
mAddonManager = nullptr;
|
||||
|
||||
mWebGpu = nullptr;
|
||||
|
||||
mSharePromise = nullptr;
|
||||
}
|
||||
|
||||
void Navigator::GetUserAgent(nsAString& aUserAgent, CallerType aCallerType,
|
||||
@ -1331,6 +1336,110 @@ Promise* Navigator::GetBattery(ErrorResult& aRv) {
|
||||
return mBatteryPromise;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Navigator::Share() - Web Share API
|
||||
//*****************************************************************************
|
||||
|
||||
Promise* Navigator::Share(const ShareData& aData, ErrorResult& aRv) {
|
||||
if (NS_WARN_IF(!mWindow || !mWindow->GetDocShell() ||
|
||||
!mWindow->GetExtantDoc())) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mSharePromise) {
|
||||
NS_WARNING("Only one share picker at a time per navigator instance");
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If none of data's members title, text, or url are present, reject p with
|
||||
// TypeError, and abort these steps.
|
||||
bool someMemberPassed = aData.mTitle.WasPassed() || aData.mText.WasPassed() ||
|
||||
aData.mUrl.WasPassed();
|
||||
if (!someMemberPassed) {
|
||||
nsAutoString message;
|
||||
nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
||||
"WebShareAPI_NeedOneMember", message);
|
||||
aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(message);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// null checked above
|
||||
auto doc = mWindow->GetExtantDoc();
|
||||
|
||||
// If data's url member is present, try to resolve it...
|
||||
nsCOMPtr<nsIURI> url;
|
||||
if (aData.mUrl.WasPassed()) {
|
||||
auto result = doc->ResolveWithBaseURI(aData.mUrl.Value());
|
||||
if (NS_WARN_IF(result.isErr())) {
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(aData.mUrl.Value());
|
||||
return nullptr;
|
||||
}
|
||||
url = result.unwrap();
|
||||
}
|
||||
|
||||
// Process the title member...
|
||||
nsCString title;
|
||||
if (aData.mTitle.WasPassed()) {
|
||||
title.Assign(NS_ConvertUTF16toUTF8(aData.mTitle.Value()));
|
||||
} else {
|
||||
title.SetIsVoid(true);
|
||||
}
|
||||
|
||||
// Process the text member...
|
||||
nsCString text;
|
||||
if (aData.mText.WasPassed()) {
|
||||
text.Assign(NS_ConvertUTF16toUTF8(aData.mText.Value()));
|
||||
} else {
|
||||
text.SetIsVoid(true);
|
||||
}
|
||||
|
||||
// The spec does the "triggered by user activation" after the data checks.
|
||||
// Unfortunately, both Chrome and Safari behave this way, so interop wins.
|
||||
// https://github.com/w3c/web-share/pull/118
|
||||
if (!UserActivation::IsHandlingUserInput()) {
|
||||
NS_WARNING("Attempt to share not triggered by user activation");
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Let mSharePromise be a new promise.
|
||||
mSharePromise = Promise::Create(mWindow->AsGlobal(), aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IPCWebShareData data(title, text, url);
|
||||
auto wgc = mWindow->GetWindowGlobalChild();
|
||||
if (!wgc) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto shareResolver = [self = RefPtr<Navigator>(this)](nsresult aResult) {
|
||||
MOZ_ASSERT(self->mSharePromise);
|
||||
if (NS_SUCCEEDED(aResult)) {
|
||||
self->mSharePromise->MaybeResolveWithUndefined();
|
||||
} else {
|
||||
self->mSharePromise->MaybeReject(aResult);
|
||||
}
|
||||
self->mSharePromise = nullptr;
|
||||
};
|
||||
|
||||
auto shareRejector = [self = RefPtr<Navigator>(this)](
|
||||
mozilla::ipc::ResponseRejectReason&& aReason) {
|
||||
// IPC died or maybe page navigated...
|
||||
if (self->mSharePromise) {
|
||||
self->mSharePromise = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Do the share
|
||||
wgc->SendShare(data, shareResolver, shareRejector);
|
||||
return mSharePromise;
|
||||
}
|
||||
|
||||
already_AddRefed<LegacyMozTCPSocket> Navigator::MozTCPSocket() {
|
||||
RefPtr<LegacyMozTCPSocket> socket = new LegacyMozTCPSocket(GetWindow());
|
||||
return socket.forget();
|
||||
|
@ -80,6 +80,8 @@ class VRDisplay;
|
||||
class VRServiceTest;
|
||||
class StorageManager;
|
||||
class MediaCapabilities;
|
||||
struct ShareData;
|
||||
class WindowGlobalChild;
|
||||
|
||||
class Navigator final : public nsISupports, public nsWrapperCache {
|
||||
public:
|
||||
@ -131,6 +133,8 @@ class Navigator final : public nsISupports, public nsWrapperCache {
|
||||
Geolocation* GetGeolocation(ErrorResult& aRv);
|
||||
Promise* GetBattery(ErrorResult& aRv);
|
||||
|
||||
Promise* Share(const ShareData& aData, ErrorResult& aRv);
|
||||
|
||||
static void AppName(nsAString& aAppName, nsIPrincipal* aCallerPrincipal,
|
||||
bool aUsePrefOverriddenValue);
|
||||
|
||||
@ -276,6 +280,7 @@ class Navigator final : public nsISupports, public nsWrapperCache {
|
||||
RefPtr<dom::MediaCapabilities> mMediaCapabilities;
|
||||
RefPtr<AddonManager> mAddonManager;
|
||||
RefPtr<webgpu::Instance> mWebGpu;
|
||||
RefPtr<Promise> mSharePromise; // Web Share API related
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -28,6 +28,13 @@ struct JSWindowActorMessageMeta {
|
||||
JSWindowActorMessageKind kind;
|
||||
};
|
||||
|
||||
struct IPCWebShareData
|
||||
{
|
||||
nsCString title;
|
||||
nsCString text;
|
||||
nsIURI url;
|
||||
};
|
||||
|
||||
/**
|
||||
* A PWindowGlobal actor has a lifetime matching that of a single Window Global,
|
||||
* specifically a |nsGlobalWindowInner|. These actors will form a parent/child
|
||||
@ -77,6 +84,9 @@ parent:
|
||||
/// Notify the parent that this PWindowGlobal is now the current global.
|
||||
async BecomeCurrentWindowGlobal();
|
||||
|
||||
// Attempts to perform a "Web Share".
|
||||
async Share(IPCWebShareData aData) returns (nsresult rv);
|
||||
|
||||
async Destroy();
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,10 @@
|
||||
#include "nsFrameLoaderOwner.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsITransportSecurityInfo.h"
|
||||
#include "nsISharePicker.h"
|
||||
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
|
||||
#include "mozilla/dom/JSWindowActorBinding.h"
|
||||
#include "mozilla/dom/JSWindowActorParent.h"
|
||||
@ -302,6 +306,78 @@ bool WindowGlobalParent::IsCurrentGlobal() {
|
||||
return CanSend() && mBrowsingContext->GetCurrentWindowGlobal() == this;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ShareHandler final : public PromiseNativeHandler {
|
||||
public:
|
||||
explicit ShareHandler(
|
||||
mozilla::dom::WindowGlobalParent::ShareResolver&& aResolver)
|
||||
: mResolver(std::move(aResolver)) {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
public:
|
||||
virtual void ResolvedCallback(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue) override {
|
||||
mResolver(NS_OK);
|
||||
}
|
||||
|
||||
virtual void RejectedCallback(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue) override {
|
||||
if (NS_WARN_IF(!aValue.isObject())) {
|
||||
mResolver(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
// nsresult is stored as Exception internally in Promise
|
||||
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
|
||||
RefPtr<DOMException> unwrapped;
|
||||
nsresult rv = UNWRAP_OBJECT(DOMException, &obj, unwrapped);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mResolver(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
mResolver(unwrapped->GetResult());
|
||||
}
|
||||
|
||||
private:
|
||||
~ShareHandler() = default;
|
||||
|
||||
mozilla::dom::WindowGlobalParent::ShareResolver mResolver;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS0(ShareHandler)
|
||||
|
||||
} // namespace
|
||||
|
||||
mozilla::ipc::IPCResult WindowGlobalParent::RecvShare(
|
||||
IPCWebShareData&& aData, WindowGlobalParent::ShareResolver&& aResolver) {
|
||||
// Widget Layer handoff...
|
||||
nsCOMPtr<nsISharePicker> sharePicker =
|
||||
do_GetService("@mozilla.org/sharepicker;1");
|
||||
|
||||
if (!sharePicker) {
|
||||
aResolver(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// And finally share the data...
|
||||
RefPtr<Promise> promise;
|
||||
nsresult rv = sharePicker->Share(aData.title(), aData.text(), aData.url(),
|
||||
getter_AddRefs(promise));
|
||||
if (NS_FAILED(rv)) {
|
||||
aResolver(rv);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// Handler finally awaits response...
|
||||
RefPtr<ShareHandler> handler = new ShareHandler(std::move(aResolver));
|
||||
promise->AppendNativeHandler(handler);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> WindowGlobalParent::ChangeFrameRemoteness(
|
||||
dom::BrowsingContext* aBc, const nsAString& aRemoteType,
|
||||
uint64_t aPendingSwitchId, ErrorResult& aRv) {
|
||||
|
@ -158,6 +158,10 @@ class WindowGlobalParent final : public WindowGlobalActor,
|
||||
const Maybe<IntRect>& aRect, float aScale,
|
||||
nscolor aBackgroundColor, uint32_t aFlags);
|
||||
|
||||
// WebShare API - try to share
|
||||
mozilla::ipc::IPCResult RecvShare(IPCWebShareData&& aData,
|
||||
ShareResolver&& aResolver);
|
||||
|
||||
private:
|
||||
~WindowGlobalParent();
|
||||
|
||||
|
@ -384,3 +384,5 @@ MathML_DeprecatedMencloseNotationRadical=The “radical” value is deprecated f
|
||||
MathML_DeprecatedStyleAttributeWarning=MathML attributes “background”, “color”, “fontfamily”, “fontsize”, “fontstyle” and “fontweight” are deprecated and will be removed at a future date.
|
||||
# LOCALIZATION NOTE: Do not translate MathML and XLink.
|
||||
MathML_DeprecatedXLinkAttributeWarning=XLink attributes “href”, “type”, “show” and “actuate” are deprecated on MathML elements and will be removed at a future date.
|
||||
# LOCALIZATION NOTE: Do not translate title, text, url as they are the names of JS properties.
|
||||
WebShareAPI_NeedOneMember=title or text or url member of the ShareData dictionary. At least one of the members is required.
|
||||
|
@ -322,3 +322,15 @@ partial interface Navigator {
|
||||
[Pref="dom.events.asyncClipboard", SecureContext, SameObject]
|
||||
readonly attribute Clipboard clipboard;
|
||||
};
|
||||
|
||||
// https://wicg.github.io/web-share/#navigator-interface
|
||||
partial interface Navigator {
|
||||
[SecureContext, Throws, Pref="dom.webshare.enabled"]
|
||||
Promise<void> share(optional ShareData data = {});
|
||||
};
|
||||
// https://wicg.github.io/web-share/#sharedata-dictionary
|
||||
dictionary ShareData {
|
||||
USVString title;
|
||||
USVString text;
|
||||
USVString url;
|
||||
};
|
||||
|
@ -2693,6 +2693,12 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# WebShare API - exposes navigator.share()
|
||||
- name: dom.webshare.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Prefs starting with "editor"
|
||||
#---------------------------------------------------------------------------
|
||||
|
1
testing/web-platform/meta/web-share/__dir__.ini
Normal file
1
testing/web-platform/meta/web-share/__dir__.ini
Normal file
@ -0,0 +1 @@
|
||||
prefs: [dom.webshare.enabled:true]
|
@ -1,10 +0,0 @@
|
||||
[idlharness.https.window.html]
|
||||
[Navigator interface: operation share(ShareData)]
|
||||
expected: FAIL
|
||||
|
||||
[Navigator interface: calling share(ShareData) on navigator with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Navigator interface: navigator must inherit property "share(ShareData)" with the proper type]
|
||||
expected: FAIL
|
||||
|
@ -1,16 +0,0 @@
|
||||
[share-empty.https.html]
|
||||
[share with no arguments (same as empty dictionary)]
|
||||
expected: FAIL
|
||||
|
||||
[share with an empty dictionary]
|
||||
expected: FAIL
|
||||
|
||||
[share with a undefined argument (same as empty dictionary)]
|
||||
expected: FAIL
|
||||
|
||||
[share with a null argument (same as empty dictionary)]
|
||||
expected: FAIL
|
||||
|
||||
[share with a dictionary containing only surplus fields]
|
||||
expected: FAIL
|
||||
|
@ -1,4 +0,0 @@
|
||||
[share-sharePromise-internal-slot.https.html]
|
||||
[Only allow one share call at a time, which is controlled by the [[sharePromise\]\] internal slot.]
|
||||
expected: FAIL
|
||||
|
@ -1,4 +0,0 @@
|
||||
[share-url-invalid.https.html]
|
||||
[share with an invalid URL]
|
||||
expected: FAIL
|
||||
|
@ -1,4 +0,0 @@
|
||||
[share-without-user-gesture.https.html]
|
||||
[share without a user gesture]
|
||||
expected: FAIL
|
||||
|
@ -10,21 +10,27 @@
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<button>
|
||||
<script>
|
||||
setup({ allow_uncaught_exception:true });
|
||||
promise_test(async t => {
|
||||
const [, promise2, promise3] = await test_driver.bless(
|
||||
"share needs user activation",
|
||||
() => {
|
||||
return [
|
||||
const button = document.querySelector("button");
|
||||
const p = new Promise(r => {
|
||||
button.onclick = () => {
|
||||
const promises = [];
|
||||
promises.push(
|
||||
navigator.share({ title: "should be pending" }),
|
||||
navigator.share({ title: "should reject" }),
|
||||
navigator.share({ title: "should also reject" }),
|
||||
];
|
||||
}
|
||||
);
|
||||
navigator.share({ title: "should also reject" })
|
||||
);
|
||||
r(promises);
|
||||
};
|
||||
});
|
||||
test_driver.click(button);
|
||||
const [, promise2, promise3] = await p;
|
||||
await Promise.all([
|
||||
promise_rejects(t, "InvalidStateError", promise2),
|
||||
promise_rejects(t, "InvalidStateError", promise3),
|
||||
promise_rejects(t, "InvalidStateError", promise3)
|
||||
]);
|
||||
}, "Only allow one share call at a time, which is controlled by the [[sharePromise]] internal slot.");
|
||||
</script>
|
||||
|
@ -117,6 +117,7 @@ XPIDL_SOURCES += [
|
||||
'nsIPrintSettingsService.idl',
|
||||
'nsIScreen.idl',
|
||||
'nsIScreenManager.idl',
|
||||
'nsISharePicker.idl',
|
||||
'nsISound.idl',
|
||||
'nsITransferable.idl',
|
||||
]
|
||||
|
@ -30,6 +30,7 @@ NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SOUND_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SHAREPICKER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
||||
@ -59,6 +60,8 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
||||
{"@mozilla.org/sound;1", &kNS_SOUND_CID, Module::CONTENT_PROCESS_ONLY},
|
||||
{"@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID,
|
||||
Module::CONTENT_PROCESS_ONLY},
|
||||
{"@mozilla.org/sharepicker;1", &kNS_SHAREPICKER_CID,
|
||||
Module::CONTENT_PROCESS_ONLY},
|
||||
{nullptr}};
|
||||
|
||||
extern const mozilla::Module kContentProcessWidgetModule = {
|
||||
|
19
widget/nsISharePicker.idl
Normal file
19
widget/nsISharePicker.idl
Normal file
@ -0,0 +1,19 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, uuid(1201d357-8417-4926-a694-e6408fbedcf8)]
|
||||
interface nsISharePicker : nsISupports
|
||||
{
|
||||
/**
|
||||
* XPCOM Analog of navigator.share() as per:
|
||||
* https://w3c.github.io/web-share/#share-method
|
||||
*/
|
||||
Promise share(in AUTF8String title, in AUTF8String text, in nsIURI url);
|
||||
};
|
@ -51,6 +51,14 @@
|
||||
} \
|
||||
}
|
||||
|
||||
/*1201d357-8417-4926-a694-e6408fbedcf8*/
|
||||
#define NS_SHAREPICKER_CID \
|
||||
{ \
|
||||
0x1201d357, 0x8417, 0x4926, { \
|
||||
0xa6, 0x94, 0xe6, 0x40, 0x8f, 0xbe, 0xdc, 0xf8 \
|
||||
} \
|
||||
}
|
||||
|
||||
/* XXX the following CID's are not in order. This needs
|
||||
to be fixed. */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user