зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1114554 - Patch 5 - getNotifications() on worker thread. r=wchen
--HG-- extra : rebase_source : b3f68e725be5cbfedc2995c9b20450e4bcaa1aae
This commit is contained in:
Родитель
54e0ea7180
Коммит
811edc788a
|
@ -9,6 +9,7 @@
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
#include "mozilla/dom/OwningNonNull.h"
|
#include "mozilla/dom/OwningNonNull.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "mozilla/dom/PromiseWorkerProxy.h"
|
||||||
#include "mozilla/Move.h"
|
#include "mozilla/Move.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/unused.h"
|
#include "mozilla/unused.h"
|
||||||
|
@ -50,29 +51,29 @@ namespace dom {
|
||||||
|
|
||||||
using namespace workers;
|
using namespace workers;
|
||||||
|
|
||||||
class NotificationStorageCallback final : public nsINotificationStorageCallback
|
struct NotificationStrings
|
||||||
{
|
{
|
||||||
public:
|
const nsString mID;
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
const nsString mTitle;
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(NotificationStorageCallback)
|
const nsString mDir;
|
||||||
|
const nsString mLang;
|
||||||
|
const nsString mBody;
|
||||||
|
const nsString mTag;
|
||||||
|
const nsString mIcon;
|
||||||
|
const nsString mData;
|
||||||
|
const nsString mBehavior;
|
||||||
|
const nsString mServiceWorkerRegistrationID;
|
||||||
|
};
|
||||||
|
|
||||||
NotificationStorageCallback(nsIGlobalObject* aWindow, const nsAString& aScope,
|
class ScopeCheckingGetCallback : public nsINotificationStorageCallback
|
||||||
Promise* aPromise)
|
{
|
||||||
: mCount(0),
|
const nsString mScope;
|
||||||
mWindow(aWindow),
|
public:
|
||||||
mPromise(aPromise),
|
NS_DECL_ISUPPORTS
|
||||||
mScope(aScope)
|
|
||||||
{
|
explicit ScopeCheckingGetCallback(const nsAString& aScope)
|
||||||
AssertIsOnMainThread();
|
: mScope(aScope)
|
||||||
MOZ_ASSERT(aWindow);
|
{}
|
||||||
MOZ_ASSERT(aPromise);
|
|
||||||
AutoJSAPI jsapi;
|
|
||||||
DebugOnly<bool> ok = jsapi.Init(aWindow);
|
|
||||||
MOZ_ASSERT(ok);
|
|
||||||
// Created in the compartment of the window.
|
|
||||||
mNotifications = JS_NewArrayObject(jsapi.cx(), 0);
|
|
||||||
HoldData();
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHOD Handle(const nsAString& aID,
|
NS_IMETHOD Handle(const nsAString& aID,
|
||||||
const nsAString& aTitle,
|
const nsAString& aTitle,
|
||||||
|
@ -84,7 +85,7 @@ public:
|
||||||
const nsAString& aData,
|
const nsAString& aData,
|
||||||
const nsAString& aBehavior,
|
const nsAString& aBehavior,
|
||||||
const nsAString& aServiceWorkerRegistrationID,
|
const nsAString& aServiceWorkerRegistrationID,
|
||||||
JSContext* aCx) override
|
JSContext* aCx) final
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
MOZ_ASSERT(!aID.IsEmpty());
|
MOZ_ASSERT(!aID.IsEmpty());
|
||||||
|
@ -94,100 +95,102 @@ public:
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedDictionary<NotificationOptions> options(aCx);
|
NotificationStrings strings = {
|
||||||
options.mDir = Notification::StringToDirection(nsString(aDir));
|
nsString(aID),
|
||||||
options.mLang = aLang;
|
nsString(aTitle),
|
||||||
options.mBody = aBody;
|
nsString(aDir),
|
||||||
options.mTag = aTag;
|
nsString(aLang),
|
||||||
options.mIcon = aIcon;
|
nsString(aBody),
|
||||||
options.mMozbehavior.Init(aBehavior);
|
nsString(aTag),
|
||||||
nsRefPtr<Notification> notification;
|
nsString(aIcon),
|
||||||
notification = Notification::CreateInternal(aID,
|
nsString(aData),
|
||||||
aTitle,
|
nsString(aBehavior),
|
||||||
options);
|
nsString(aServiceWorkerRegistrationID),
|
||||||
notification->BindToOwner(mWindow);
|
};
|
||||||
ErrorResult rv;
|
|
||||||
notification->InitFromBase64(aCx, aData, rv);
|
|
||||||
if (rv.Failed()) {
|
|
||||||
return rv.StealNSResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
notification->SetScope(aServiceWorkerRegistrationID);
|
mStrings.AppendElement(Move(strings));
|
||||||
|
|
||||||
notification->SetStoredState(true);
|
|
||||||
|
|
||||||
AutoJSAPI jsapi;
|
|
||||||
DebugOnly<bool> ok = jsapi.Init(mWindow, aCx);
|
|
||||||
MOZ_ASSERT(ok);
|
|
||||||
|
|
||||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
JS::Rooted<JSObject*> notifications(aCx, mNotifications);
|
|
||||||
if (!JS_DefineElement(aCx, notifications, mCount++, element, 0)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHOD Done(JSContext* aCx) override
|
NS_IMETHOD Done(JSContext* aCx) override = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~ScopeCheckingGetCallback()
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsTArray<NotificationStrings> mStrings;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(ScopeCheckingGetCallback, nsINotificationStorageCallback)
|
||||||
|
|
||||||
|
class NotificationStorageCallback final : public ScopeCheckingGetCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS(NotificationStorageCallback)
|
||||||
|
|
||||||
|
NotificationStorageCallback(nsIGlobalObject* aWindow, const nsAString& aScope,
|
||||||
|
Promise* aPromise)
|
||||||
|
: ScopeCheckingGetCallback(aScope),
|
||||||
|
mWindow(aWindow),
|
||||||
|
mPromise(aPromise)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
MOZ_ASSERT(aWindow);
|
||||||
|
MOZ_ASSERT(aPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Done(JSContext* aCx) final
|
||||||
{
|
{
|
||||||
AutoJSAPI jsapi;
|
AutoJSAPI jsapi;
|
||||||
DebugOnly<bool> ok = jsapi.Init(mWindow, aCx);
|
DebugOnly<bool> ok = jsapi.Init(mWindow, aCx);
|
||||||
MOZ_ASSERT(ok);
|
MOZ_ASSERT(ok);
|
||||||
|
|
||||||
JS::Rooted<JS::Value> result(aCx, JS::ObjectValue(*mNotifications));
|
ErrorResult result;
|
||||||
mPromise->MaybeResolve(aCx, result);
|
nsAutoTArray<nsRefPtr<Notification>, 5> notifications;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mStrings.Length(); ++i) {
|
||||||
|
nsRefPtr<Notification> n =
|
||||||
|
Notification::ConstructFromFields(mWindow,
|
||||||
|
mStrings[i].mID,
|
||||||
|
mStrings[i].mTitle,
|
||||||
|
mStrings[i].mDir,
|
||||||
|
mStrings[i].mLang,
|
||||||
|
mStrings[i].mBody,
|
||||||
|
mStrings[i].mTag,
|
||||||
|
mStrings[i].mIcon,
|
||||||
|
mStrings[i].mData,
|
||||||
|
/* mStrings[i].mBehavior, not
|
||||||
|
* supported */
|
||||||
|
mStrings[i].mServiceWorkerRegistrationID,
|
||||||
|
result);
|
||||||
|
|
||||||
|
n->SetStoredState(true);
|
||||||
|
unused << NS_WARN_IF(result.Failed());
|
||||||
|
if (!result.Failed()) {
|
||||||
|
notifications.AppendElement(n.forget());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mPromise->MaybeResolve(notifications);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~NotificationStorageCallback()
|
virtual ~NotificationStorageCallback()
|
||||||
{
|
{}
|
||||||
DropData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HoldData()
|
|
||||||
{
|
|
||||||
mozilla::HoldJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DropData()
|
|
||||||
{
|
|
||||||
mNotifications = nullptr;
|
|
||||||
mozilla::DropJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t mCount;
|
|
||||||
nsCOMPtr<nsIGlobalObject> mWindow;
|
nsCOMPtr<nsIGlobalObject> mWindow;
|
||||||
nsRefPtr<Promise> mPromise;
|
nsRefPtr<Promise> mPromise;
|
||||||
JS::Heap<JSObject *> mNotifications;
|
|
||||||
const nsString mScope;
|
const nsString mScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(NotificationStorageCallback)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(NotificationStorageCallback)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(NotificationStorageCallback)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(NotificationStorageCallback)
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationStorageCallback)
|
NS_IMPL_CYCLE_COLLECTION(NotificationStorageCallback, mWindow, mPromise);
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NotificationStorageCallback)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NotificationStorageCallback)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsINotificationStorageCallback)
|
NS_INTERFACE_MAP_END_INHERITING(ScopeCheckingGetCallback)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(NotificationStorageCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNotifications)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NotificationStorageCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NotificationStorageCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
|
|
||||||
tmp->DropData();
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
class NotificationGetRunnable final : public nsRunnable
|
class NotificationGetRunnable final : public nsRunnable
|
||||||
{
|
{
|
||||||
|
@ -369,7 +372,7 @@ protected:
|
||||||
{
|
{
|
||||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true);
|
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true);
|
||||||
WorkerRunInternal();
|
WorkerRunInternal(aCx, aWorkerPrivate);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +384,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
WorkerRunInternal() = 0;
|
WorkerRunInternal(JSContext* aCx, WorkerPrivate* aWorkerPrivate) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Overrides dispatch and run handlers so we can directly dispatch from main
|
// Overrides dispatch and run handlers so we can directly dispatch from main
|
||||||
|
@ -399,7 +402,7 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
WorkerRunInternal() override
|
WorkerRunInternal(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||||
{
|
{
|
||||||
mNotification->DispatchTrustedEvent(mEventName);
|
mNotification->DispatchTrustedEvent(mEventName);
|
||||||
}
|
}
|
||||||
|
@ -707,6 +710,10 @@ void
|
||||||
Notification::SetAlertName()
|
Notification::SetAlertName()
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
if (!mAlertName.IsEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoString alertName;
|
nsAutoString alertName;
|
||||||
DebugOnly<nsresult> rv = GetOrigin(GetPrincipal(), alertName);
|
DebugOnly<nsresult> rv = GetOrigin(GetPrincipal(), alertName);
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "GetOrigin should not have failed");
|
MOZ_ASSERT(NS_SUCCEEDED(rv), "GetOrigin should not have failed");
|
||||||
|
@ -743,7 +750,7 @@ Notification::Constructor(const GlobalObject& aGlobal,
|
||||||
|
|
||||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
nsRefPtr<Notification> notification =
|
nsRefPtr<Notification> notification =
|
||||||
CreateAndShow(global, aTitle, aOptions, aRv);
|
CreateAndShow(global, aTitle, aOptions, EmptyString(), aRv);
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -765,7 +772,7 @@ Notification::ConstructFromFields(
|
||||||
const nsAString& aTag,
|
const nsAString& aTag,
|
||||||
const nsAString& aIcon,
|
const nsAString& aIcon,
|
||||||
const nsAString& aData,
|
const nsAString& aData,
|
||||||
const nsAString& aScope,
|
const nsAString& aServiceWorkerRegistrationID,
|
||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aGlobal);
|
MOZ_ASSERT(aGlobal);
|
||||||
|
@ -794,7 +801,7 @@ Notification::ConstructFromFields(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
notification->SetScope(aScope);
|
notification->SetScope(aServiceWorkerRegistrationID);
|
||||||
|
|
||||||
return notification.forget();
|
return notification.forget();
|
||||||
}
|
}
|
||||||
|
@ -990,7 +997,7 @@ protected:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
WorkerRunInternal() override
|
WorkerRunInternal(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||||
{
|
{
|
||||||
UniquePtr<NotificationRef> ref;
|
UniquePtr<NotificationRef> ref;
|
||||||
mozilla::Swap(ref, mNotificationRef);
|
mozilla::Swap(ref, mNotificationRef);
|
||||||
|
@ -1101,7 +1108,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WorkerRunInternal() override
|
WorkerRunInternal(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||||
{
|
{
|
||||||
bool doDefaultAction = mNotification->DispatchClickEvent();
|
bool doDefaultAction = mNotification->DispatchClickEvent();
|
||||||
MOZ_ASSERT_IF(mWorkerPrivate->IsServiceWorker(), !doDefaultAction);
|
MOZ_ASSERT_IF(mWorkerPrivate->IsServiceWorker(), !doDefaultAction);
|
||||||
|
@ -1695,6 +1702,198 @@ Notification::Get(const GlobalObject& aGlobal,
|
||||||
return Get(window, aFilter, EmptyString(), aRv);
|
return Get(window, aFilter, EmptyString(), aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WorkerGetResultRunnable final : public NotificationWorkerRunnable
|
||||||
|
{
|
||||||
|
nsRefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||||
|
const nsTArray<NotificationStrings> mStrings;
|
||||||
|
public:
|
||||||
|
WorkerGetResultRunnable(WorkerPrivate* aWorkerPrivate,
|
||||||
|
PromiseWorkerProxy* aPromiseProxy,
|
||||||
|
const nsTArray<NotificationStrings>&& aStrings)
|
||||||
|
: NotificationWorkerRunnable(aWorkerPrivate)
|
||||||
|
, mPromiseProxy(aPromiseProxy)
|
||||||
|
, mStrings(Move(aStrings))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerRunInternal(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||||
|
{
|
||||||
|
nsRefPtr<Promise> workerPromise = mPromiseProxy->GetWorkerPromise();
|
||||||
|
|
||||||
|
ErrorResult result;
|
||||||
|
nsAutoTArray<nsRefPtr<Notification>, 5> notifications;
|
||||||
|
for (uint32_t i = 0; i < mStrings.Length(); ++i) {
|
||||||
|
nsRefPtr<Notification> n =
|
||||||
|
Notification::ConstructFromFields(aWorkerPrivate->GlobalScope(),
|
||||||
|
mStrings[i].mID,
|
||||||
|
mStrings[i].mTitle,
|
||||||
|
mStrings[i].mDir,
|
||||||
|
mStrings[i].mLang,
|
||||||
|
mStrings[i].mBody,
|
||||||
|
mStrings[i].mTag,
|
||||||
|
mStrings[i].mIcon,
|
||||||
|
mStrings[i].mData,
|
||||||
|
/* mStrings[i].mBehavior, not
|
||||||
|
* supported */
|
||||||
|
mStrings[i].mServiceWorkerRegistrationID,
|
||||||
|
result);
|
||||||
|
|
||||||
|
n->SetStoredState(true);
|
||||||
|
unused << NS_WARN_IF(result.Failed());
|
||||||
|
if (!result.Failed()) {
|
||||||
|
notifications.AppendElement(n.forget());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
workerPromise->MaybeResolve(notifications);
|
||||||
|
mPromiseProxy->CleanUp(aCx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WorkerGetCallback final : public ScopeCheckingGetCallback
|
||||||
|
{
|
||||||
|
nsRefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
WorkerGetCallback(PromiseWorkerProxy* aProxy, const nsAString& aScope)
|
||||||
|
: ScopeCheckingGetCallback(aScope), mPromiseProxy(aProxy)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
MOZ_ASSERT(aProxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Done(JSContext* aCx) final
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
MOZ_ASSERT(mPromiseProxy, "Was Done() called twice?");
|
||||||
|
MutexAutoLock lock(mPromiseProxy->GetCleanUpLock());
|
||||||
|
if (mPromiseProxy->IsClean()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mPromiseProxy->GetWorkerPrivate());
|
||||||
|
nsRefPtr<WorkerGetResultRunnable> r =
|
||||||
|
new WorkerGetResultRunnable(mPromiseProxy->GetWorkerPrivate(),
|
||||||
|
mPromiseProxy,
|
||||||
|
Move(mStrings));
|
||||||
|
|
||||||
|
if (!r->Dispatch(aCx)) {
|
||||||
|
nsRefPtr<PromiseWorkerProxyControlRunnable> cr =
|
||||||
|
new PromiseWorkerProxyControlRunnable(mPromiseProxy->GetWorkerPrivate(),
|
||||||
|
mPromiseProxy);
|
||||||
|
|
||||||
|
DebugOnly<bool> ok = cr->Dispatch(aCx);
|
||||||
|
MOZ_ASSERT(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
mPromiseProxy = nullptr;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~WorkerGetCallback()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS_INHERITED0(WorkerGetCallback, ScopeCheckingGetCallback)
|
||||||
|
|
||||||
|
class WorkerGetRunnable final : public nsRunnable
|
||||||
|
{
|
||||||
|
nsRefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||||
|
const nsString mTag;
|
||||||
|
const nsString mScope;
|
||||||
|
public:
|
||||||
|
WorkerGetRunnable(WorkerPrivate* aWorkerPrivate,
|
||||||
|
Promise* aWorkerPromise,
|
||||||
|
const nsAString& aTag,
|
||||||
|
const nsAString& aScope)
|
||||||
|
: mTag(aTag), mScope(aScope)
|
||||||
|
{
|
||||||
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
mPromiseProxy =
|
||||||
|
PromiseWorkerProxy::Create(aWorkerPrivate,
|
||||||
|
aWorkerPromise);
|
||||||
|
|
||||||
|
if (!mPromiseProxy || !mPromiseProxy->GetWorkerPromise()) {
|
||||||
|
aWorkerPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||||
|
mPromiseProxy = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
Run() override
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
if (!mPromiseProxy) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsINotificationStorageCallback> callback =
|
||||||
|
new WorkerGetCallback(mPromiseProxy, mScope);
|
||||||
|
|
||||||
|
AutoJSAPI jsapi;
|
||||||
|
jsapi.Init();
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsINotificationStorage> notificationStorage =
|
||||||
|
do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID, &rv);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
callback->Done(jsapi.cx());
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutexAutoLock lock(mPromiseProxy->GetCleanUpLock());
|
||||||
|
if (mPromiseProxy->IsClean()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString origin;
|
||||||
|
rv =
|
||||||
|
Notification::GetOrigin(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(),
|
||||||
|
origin);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
callback->Done(jsapi.cx());
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = notificationStorage->Get(origin, mTag, callback);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
callback->Done(jsapi.cx());
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
~WorkerGetRunnable()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
already_AddRefed<Promise>
|
||||||
|
Notification::WorkerGet(WorkerPrivate* aWorkerPrivate,
|
||||||
|
const GetNotificationOptions& aFilter,
|
||||||
|
const nsAString& aScope,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
nsRefPtr<Promise> p = Promise::Create(aWorkerPrivate->GlobalScope(), aRv);
|
||||||
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<WorkerGetRunnable> r =
|
||||||
|
new WorkerGetRunnable(aWorkerPrivate, p, aFilter.mTag, aScope);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(r)))) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.forget();
|
||||||
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
Notification::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
Notification::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
{
|
{
|
||||||
|
@ -1724,12 +1923,14 @@ Notification::Close()
|
||||||
void
|
void
|
||||||
Notification::CloseInternal()
|
Notification::CloseInternal()
|
||||||
{
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
// Transfer ownership (if any) to local scope so we can release it at the end
|
// Transfer ownership (if any) to local scope so we can release it at the end
|
||||||
// of this function. This is relevant when the call is from
|
// of this function. This is relevant when the call is from
|
||||||
// NotificationTask::Run().
|
// NotificationTask::Run().
|
||||||
UniquePtr<NotificationRef> ownership;
|
UniquePtr<NotificationRef> ownership;
|
||||||
mozilla::Swap(ownership, mTempRef);
|
mozilla::Swap(ownership, mTempRef);
|
||||||
|
|
||||||
|
SetAlertName();
|
||||||
UnpersistNotification();
|
UnpersistNotification();
|
||||||
if (!mIsClosed) {
|
if (!mIsClosed) {
|
||||||
nsCOMPtr<nsIAlertsService> alertService =
|
nsCOMPtr<nsIAlertsService> alertService =
|
||||||
|
@ -2052,13 +2253,11 @@ Notification::ShowPersistentNotification(nsIGlobalObject *aGlobal,
|
||||||
p->MaybeResolve(JS::UndefinedHandleValue);
|
p->MaybeResolve(JS::UndefinedHandleValue);
|
||||||
|
|
||||||
nsRefPtr<Notification> notification =
|
nsRefPtr<Notification> notification =
|
||||||
CreateAndShow(aGlobal, aTitle, aOptions, aRv);
|
CreateAndShow(aGlobal, aTitle, aOptions, aScope, aRv);
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
notification->SetScope(aScope);
|
|
||||||
|
|
||||||
return p.forget();
|
return p.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2066,6 +2265,7 @@ Notification::ShowPersistentNotification(nsIGlobalObject *aGlobal,
|
||||||
Notification::CreateAndShow(nsIGlobalObject* aGlobal,
|
Notification::CreateAndShow(nsIGlobalObject* aGlobal,
|
||||||
const nsAString& aTitle,
|
const nsAString& aTitle,
|
||||||
const NotificationOptions& aOptions,
|
const NotificationOptions& aOptions,
|
||||||
|
const nsAString& aScope,
|
||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aGlobal);
|
MOZ_ASSERT(aGlobal);
|
||||||
|
@ -2087,6 +2287,8 @@ Notification::CreateAndShow(nsIGlobalObject* aGlobal,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notification->SetScope(aScope);
|
||||||
|
|
||||||
auto ref = MakeUnique<NotificationRef>(notification);
|
auto ref = MakeUnique<NotificationRef>(notification);
|
||||||
if (!ref->Initialized()) {
|
if (!ref->Initialized()) {
|
||||||
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
|
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
|
||||||
|
|
|
@ -116,6 +116,7 @@ class Notification : public DOMEventTargetHelper
|
||||||
friend class NotificationObserver;
|
friend class NotificationObserver;
|
||||||
friend class NotificationStorageCallback;
|
friend class NotificationStorageCallback;
|
||||||
friend class ServiceWorkerNotificationObserver;
|
friend class ServiceWorkerNotificationObserver;
|
||||||
|
friend class WorkerGetRunnable;
|
||||||
friend class WorkerNotificationObserver;
|
friend class WorkerNotificationObserver;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -157,7 +158,7 @@ public:
|
||||||
const nsAString& aTag,
|
const nsAString& aTag,
|
||||||
const nsAString& aIcon,
|
const nsAString& aIcon,
|
||||||
const nsAString& aData,
|
const nsAString& aData,
|
||||||
const nsAString& aScope,
|
const nsAString& aServiceWorkerRegistrationID,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
void GetID(nsAString& aRetval) {
|
void GetID(nsAString& aRetval) {
|
||||||
|
@ -225,6 +226,11 @@ public:
|
||||||
const GetNotificationOptions& aFilter,
|
const GetNotificationOptions& aFilter,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
static already_AddRefed<Promise> WorkerGet(workers::WorkerPrivate* aWorkerPrivate,
|
||||||
|
const GetNotificationOptions& aFilter,
|
||||||
|
const nsAString& aScope,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
// Notification implementation of
|
// Notification implementation of
|
||||||
// ServiceWorkerRegistration.showNotification.
|
// ServiceWorkerRegistration.showNotification.
|
||||||
static already_AddRefed<Promise>
|
static already_AddRefed<Promise>
|
||||||
|
@ -384,6 +390,7 @@ private:
|
||||||
CreateAndShow(nsIGlobalObject* aGlobal,
|
CreateAndShow(nsIGlobalObject* aGlobal,
|
||||||
const nsAString& aTitle,
|
const nsAString& aTitle,
|
||||||
const NotificationOptions& aOptions,
|
const NotificationOptions& aOptions,
|
||||||
|
const nsAString& aScope,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
nsIPrincipal* GetPrincipal();
|
nsIPrincipal* GetPrincipal();
|
||||||
|
|
|
@ -1611,9 +1611,9 @@ PromiseWorkerProxy::RunCallback(JSContext* aCx,
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
MutexAutoLock lock(mCleanUpLock);
|
MutexAutoLock lock(GetCleanUpLock());
|
||||||
// If the worker thread's been cancelled we don't need to resolve the Promise.
|
// If the worker thread's been cancelled we don't need to resolve the Promise.
|
||||||
if (mCleanedUp) {
|
if (IsClean()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1063,8 +1063,7 @@ ServiceWorkerRegistrationWorkerThread::ShowNotification(JSContext* aCx,
|
||||||
already_AddRefed<Promise>
|
already_AddRefed<Promise>
|
||||||
ServiceWorkerRegistrationWorkerThread::GetNotifications(const GetNotificationOptions& aOptions, ErrorResult& aRv)
|
ServiceWorkerRegistrationWorkerThread::GetNotifications(const GetNotificationOptions& aOptions, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(false);
|
return Notification::WorkerGet(mWorkerPrivate, aOptions, mScope, aRv);
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // dom namespace
|
} // dom namespace
|
||||||
|
|
Загрузка…
Ссылка в новой задаче