mirror of
https://github.com/zen-browser/desktop.git
synced 2025-09-05 19:08:18 +00:00
chore: Made a functioning API for sharing, b=(no-bug), c=common
This commit is contained in:
@@ -1,4 +1,15 @@
|
||||
/* 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 "ZenCommonUtils.h"
|
||||
#include "nsGlobalWindowOuter.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsISharePicker.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#if defined(XP_WIN)
|
||||
# include "mozilla/WindowsVersion.h"
|
||||
#endif
|
||||
@@ -7,11 +18,44 @@ namespace zen {
|
||||
|
||||
// Use the macro to inject all of the definitions for nsISupports.
|
||||
NS_IMPL_ISUPPORTS(ZenCommonUtils, nsIZenCommonUtils)
|
||||
using WindowGlobalChild = mozilla::dom::WindowGlobalChild;
|
||||
|
||||
ZenCommonUtils::ZenCommonUtils(nsGlobalWindowOuter* aWindow) {
|
||||
nsCOMPtr<nsISupports> supports = do_QueryObject(aWindow);
|
||||
mWindow = do_GetWeakReference(supports);
|
||||
namespace {
|
||||
/**
|
||||
* @brief Helper function to fetch the most recent window proxy.
|
||||
* @param aWindow The window to query.
|
||||
* @returns The most recent window.
|
||||
*/
|
||||
static nsresult GetMostRecentWindowProxy(mozIDOMWindowProxy** aWindow) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowMediator> med(
|
||||
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (med) return med->GetMostRecentBrowserWindow(aWindow);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
/**
|
||||
* @brief Helper function to query and get a reference to the window.
|
||||
* @param aWindow The window to query.
|
||||
*/
|
||||
static nsCOMPtr<mozIDOMWindowProxy> GetMostRecentWindow() {
|
||||
nsCOMPtr<mozIDOMWindowProxy> aWindow;
|
||||
nsresult rv = GetMostRecentWindowProxy(getter_AddRefs(aWindow));
|
||||
if (NS_FAILED(rv) || !aWindow) {
|
||||
return nullptr;
|
||||
}
|
||||
return aWindow;
|
||||
}
|
||||
}
|
||||
|
||||
using mozilla::dom::WindowGlobalChild;
|
||||
using Promise = mozilla::dom::Promise;
|
||||
|
||||
#define NS_ZEN_CAN_SHARE_FAILURE() \
|
||||
*canShare = false; \
|
||||
return NS_OK;
|
||||
|
||||
/*
|
||||
* @brief Check if the current context can share data.
|
||||
@@ -19,73 +63,54 @@ ZenCommonUtils::ZenCommonUtils(nsGlobalWindowOuter* aWindow) {
|
||||
* @returns True if the current context can share data, false otherwise.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
ZenCommonUtils::CanShare(const nsIDOMWindow& aWindow, bool* canShare) {
|
||||
if (!aWindow || !aWindow->IsFullyActive()) {
|
||||
*canShare = false;
|
||||
return NS_OK;
|
||||
ZenCommonUtils::CanShare(bool* canShare) {
|
||||
auto aWindow = GetMostRecentWindow();
|
||||
if (!aWindow) {
|
||||
NS_ZEN_CAN_SHARE_FAILURE();
|
||||
}
|
||||
*canShare = IsSharingSupported();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ZenCommonUtils::Share(const nsIDOMWindow& aWindow, const nsAString& url,
|
||||
const nsAString& title, const nsAString& text,
|
||||
mozilla::dom::Promise** _retval) {
|
||||
if (!aWindow || !aWindow->IsFullyActive()) {
|
||||
ZenCommonUtils::Share(nsIURI* url, const nsACString& title,
|
||||
const nsACString& text, mozilla::dom::Promise** _retval) {
|
||||
auto aWindow = GetMostRecentWindow();
|
||||
if (!aWindow) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
if (!IsSharingSupported()) {
|
||||
return NS_OK; // We don't want to throw an error here
|
||||
}
|
||||
if (!IsSharingSupported()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
if (url.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (title.IsEmpty() && text.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (aWindow->GetExtantDoc()) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aWindow->GetExtantDoc()->ResolveWithBaseURI(url, getter_AddRefs(uri));
|
||||
if (NS_FAILED(rv) || !uri) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
if (mSharePromise) {
|
||||
NS_WARNING("Only one share picker at a time per navigator instance");
|
||||
return NS_ERROR_INVALID_STATE;
|
||||
}
|
||||
mSharePromise = Promise::Create(aWindow, __func__);
|
||||
if (!mSharePromise) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
IPCWebShareData data(title, text, url);
|
||||
auto wgc = aWindow->GetWindowGlobalChild();
|
||||
if (!wgc) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
wgc->SendShare(data)->Then(
|
||||
GetCurrentSerialEventTarget(), __func__,
|
||||
[self = RefPtr{this}](
|
||||
PWindowGlobalChild::SharePromise::ResolveOrRejectValue&& aResult) {
|
||||
if (aResult.IsResolve()) {
|
||||
if (NS_SUCCEEDED(aResult.ResolveValue())) {
|
||||
self->mSharePromise->MaybeResolveWithUndefined();
|
||||
} else {
|
||||
self->mSharePromise->MaybeReject(aResult.ResolveValue());
|
||||
}
|
||||
} else if (self->mSharePromise) {
|
||||
// IPC died
|
||||
self->mSharePromise->MaybeReject(NS_BINDING_ABORTED);
|
||||
}
|
||||
self->mSharePromise = nullptr;
|
||||
});
|
||||
*_retval = ShareInternal(aWindow, url, title, text);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mozilla::dom::Promise* ZenCommonUtils::ShareInternal(nsCOMPtr<mozIDOMWindowProxy>& aWindow, nsIURI* url,
|
||||
const nsACString& title, const nsACString& text) {
|
||||
// We shoud've had done pointer checks before, so we can assume
|
||||
// aWindow is valid.
|
||||
nsCOMPtr<nsISharePicker> sharePicker =
|
||||
do_GetService("@mozilla.org/sharepicker;1");
|
||||
if (!sharePicker) {
|
||||
return nullptr;
|
||||
}
|
||||
sharePicker->Init(aWindow);
|
||||
RefPtr<Promise> promise;
|
||||
nsresult rv = sharePicker->Share(title, text, url, getter_AddRefs(promise));
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
auto ZenCommonUtils::IsSharingSupported() -> bool {
|
||||
#if defined(XP_WIN) && !defined(__MINGW32__)
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
return false;
|
||||
#elif defined(XP_WIN) && !defined(__MINGW32__)
|
||||
// The first public build that supports ShareCanceled API
|
||||
return IsWindows10BuildOrLater(18956);
|
||||
#else
|
||||
|
@@ -5,9 +5,12 @@
|
||||
#ifndef mozilla_nsZenCommonUtils_h__
|
||||
#define mozilla_nsZenCommonUtils_h__
|
||||
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIZenCommonUtils.h"
|
||||
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsGlobalWindowOuter.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
namespace zen {
|
||||
|
||||
/**
|
||||
@@ -22,15 +25,23 @@ class ZenCommonUtils final : public nsIZenCommonUtils {
|
||||
|
||||
private:
|
||||
~ZenCommonUtils() = default;
|
||||
|
||||
RefPtr<mozilla::dom::Promise> mSharePromise; // Web Share API related
|
||||
|
||||
/**
|
||||
* @brief Check if the current context can share data.
|
||||
* @param data The data to share.
|
||||
* @returns True if the current context can share data, false otherwise.
|
||||
*/
|
||||
static auto IsSharingSupported() -> bool;
|
||||
/**
|
||||
* @brief Helper function to share data via the native dialogs.
|
||||
* @param aWindow The window to use for the share dialog.
|
||||
* @param url The URL to share.
|
||||
* @param title The title of the share.
|
||||
* @param text The text to share.
|
||||
* @returns A promise that resolves when the share is complete.
|
||||
*/
|
||||
static auto ShareInternal(nsCOMPtr<mozIDOMWindowProxy>& aWindow, nsIURI* url,
|
||||
const nsACString& title, const nsACString& text)
|
||||
-> mozilla::dom::Promise*;
|
||||
};
|
||||
|
||||
} // namespace zen
|
||||
|
@@ -5,6 +5,7 @@ Classes = [
|
||||
'contract_ids': ['@mozilla.org/zen/common-utils;1'],
|
||||
'type': 'zen::ZenCommonUtils',
|
||||
'headers': ['mozilla/ZenCommonUtils.h'],
|
||||
'js_name': 'zenCommonUtils',
|
||||
'js_name': 'zen',
|
||||
'processes': ProcessSelector.MAIN_PROCESS_ONLY,
|
||||
},
|
||||
]
|
||||
|
@@ -1,5 +1,4 @@
|
||||
|
||||
XPIDL_MODULE = "zen"
|
||||
XPIDL_SOURCES += [
|
||||
"nsIZenCommonUtils.idl",
|
||||
]
|
||||
@@ -8,10 +7,28 @@ EXPORTS.mozilla += [
|
||||
"ZenCommonUtils.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
SOURCES += [
|
||||
"ZenCommonUtils.cpp",
|
||||
]
|
||||
|
||||
XPCOM_MANIFESTS += [
|
||||
"components.conf",
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"/dom/base",
|
||||
"/dom/ipc",
|
||||
"/gfx/2d",
|
||||
"/layout/base",
|
||||
"/layout/forms",
|
||||
"/layout/generic",
|
||||
"/layout/painting",
|
||||
"/layout/xul",
|
||||
"/layout/xul/tree/",
|
||||
"/view",
|
||||
"/widget",
|
||||
"/widget/headless",
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
XPIDL_MODULE = "zen"
|
||||
|
@@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIDOMWindow.idl"
|
||||
#include "nsIURI.idl"
|
||||
|
||||
/**
|
||||
* @brief Common utility functions for Zen.
|
||||
@@ -18,13 +18,12 @@ interface nsIZenCommonUtils : nsISupports {
|
||||
* @param text The text to share.
|
||||
* @returns A promise that resolves when the share is complete.
|
||||
*/
|
||||
Promise share(in nsIDOMWindow window, in AString url,
|
||||
in AString title, in AString text);
|
||||
Promise share(in nsIURI url, in ACString title, in ACString text);
|
||||
/*
|
||||
* @brief Check if the current context can share data.
|
||||
* @param window The window to check.
|
||||
* @returns True if the current context can share data, false otherwise.
|
||||
*/
|
||||
boolean canShare(in nsIDOMWindow window);
|
||||
boolean canShare();
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user