mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 916893 - Patch 2 - Deal with onclose. Some grammar fixes. r=wchen
This commit is contained in:
parent
5aa559655d
commit
d9c7bbd18b
@ -340,11 +340,14 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Create one whenever you require ownership of the notification. Use with
|
||||||
|
// UniquePtr<>. See Notification.h for details.
|
||||||
class NotificationRef final {
|
class NotificationRef final {
|
||||||
friend class WorkerNotificationObserver;
|
friend class WorkerNotificationObserver;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Notification* mNotification;
|
Notification* mNotification;
|
||||||
|
bool mInited;
|
||||||
|
|
||||||
// Only useful for workers.
|
// Only useful for workers.
|
||||||
void
|
void
|
||||||
@ -364,12 +367,22 @@ public:
|
|||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
mNotification->AddRefObject();
|
mInited = mNotification->AddRefObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is only required because Gecko runs script in a worker's onclose
|
||||||
|
// handler (non-standard, Bug 790919) where calls to AddFeature() will fail.
|
||||||
|
// Due to non-standardness and added complications if we decide to support
|
||||||
|
// this, attempts to create a Notification in onclose just throw exceptions.
|
||||||
|
bool
|
||||||
|
Initialized()
|
||||||
|
{
|
||||||
|
return mInited;
|
||||||
}
|
}
|
||||||
|
|
||||||
~NotificationRef()
|
~NotificationRef()
|
||||||
{
|
{
|
||||||
if (mNotification) {
|
if (Initialized() && mNotification) {
|
||||||
if (mNotification->mWorkerPrivate && NS_IsMainThread()) {
|
if (mNotification->mWorkerPrivate && NS_IsMainThread()) {
|
||||||
nsRefPtr<ReleaseNotificationControlRunnable> r =
|
nsRefPtr<ReleaseNotificationControlRunnable> r =
|
||||||
new ReleaseNotificationControlRunnable(mNotification);
|
new ReleaseNotificationControlRunnable(mNotification);
|
||||||
@ -390,6 +403,7 @@ public:
|
|||||||
Notification*
|
Notification*
|
||||||
GetNotification()
|
GetNotification()
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(Initialized());
|
||||||
return mNotification;
|
return mNotification;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -667,10 +681,15 @@ Notification::Constructor(const GlobalObject& aGlobal,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto n = MakeUnique<NotificationRef>(notification);
|
auto ref = MakeUnique<NotificationRef>(notification);
|
||||||
|
if (!ref->Initialized()) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Queue a task to show the notification.
|
// Queue a task to show the notification.
|
||||||
nsCOMPtr<nsIRunnable> showNotificationTask =
|
nsCOMPtr<nsIRunnable> showNotificationTask =
|
||||||
new NotificationTask(Move(n), NotificationTask::eShow);
|
new NotificationTask(Move(ref), NotificationTask::eShow);
|
||||||
nsresult rv = NS_DispatchToMainThread(showNotificationTask);
|
nsresult rv = NS_DispatchToMainThread(showNotificationTask);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
notification->DispatchTrustedEvent(NS_LITERAL_STRING("error"));
|
notification->DispatchTrustedEvent(NS_LITERAL_STRING("error"));
|
||||||
@ -832,7 +851,6 @@ nsIPrincipal*
|
|||||||
Notification::GetPrincipal()
|
Notification::GetPrincipal()
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
MOZ_ASSERT_IF(mWorkerPrivate, mFeature);
|
|
||||||
if (mWorkerPrivate) {
|
if (mWorkerPrivate) {
|
||||||
return mWorkerPrivate->GetPrincipal();
|
return mWorkerPrivate->GetPrincipal();
|
||||||
} else {
|
} else {
|
||||||
@ -1413,6 +1431,9 @@ Notification::Close()
|
|||||||
{
|
{
|
||||||
AssertIsOnTargetThread();
|
AssertIsOnTargetThread();
|
||||||
auto ref = MakeUnique<NotificationRef>(this);
|
auto ref = MakeUnique<NotificationRef>(this);
|
||||||
|
if (!ref->Initialized()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> closeNotificationTask =
|
nsCOMPtr<nsIRunnable> closeNotificationTask =
|
||||||
new NotificationTask(Move(ref), NotificationTask::eClose);
|
new NotificationTask(Move(ref), NotificationTask::eClose);
|
||||||
@ -1532,17 +1553,20 @@ void Notification::InitFromBase64(JSContext* aCx, const nsAString& aData,
|
|||||||
mDataObjectContainer = container;
|
mDataObjectContainer = container;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
Notification::AddRefObject()
|
Notification::AddRefObject()
|
||||||
{
|
{
|
||||||
AssertIsOnTargetThread();
|
AssertIsOnTargetThread();
|
||||||
AddRef();
|
MOZ_ASSERT_IF(mWorkerPrivate && !mFeature, mTaskCount == 0);
|
||||||
MOZ_ASSERT_IF(mWorkerPrivate&& !mFeature, mTaskCount == 0);
|
|
||||||
MOZ_ASSERT_IF(mWorkerPrivate && mFeature, mTaskCount > 0);
|
MOZ_ASSERT_IF(mWorkerPrivate && mFeature, mTaskCount > 0);
|
||||||
if (mWorkerPrivate && !mFeature) {
|
if (mWorkerPrivate && !mFeature) {
|
||||||
RegisterFeature();
|
if (!RegisterFeature()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
AddRef();
|
||||||
++mTaskCount;
|
++mTaskCount;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1550,9 +1574,10 @@ Notification::ReleaseObject()
|
|||||||
{
|
{
|
||||||
AssertIsOnTargetThread();
|
AssertIsOnTargetThread();
|
||||||
MOZ_ASSERT(mTaskCount > 0);
|
MOZ_ASSERT(mTaskCount > 0);
|
||||||
|
MOZ_ASSERT_IF(mWorkerPrivate, mFeature);
|
||||||
|
|
||||||
--mTaskCount;
|
--mTaskCount;
|
||||||
if (mWorkerPrivate && mFeature && mTaskCount == 0) {
|
if (mWorkerPrivate && mTaskCount == 0) {
|
||||||
UnregisterFeature();
|
UnregisterFeature();
|
||||||
}
|
}
|
||||||
Release();
|
Release();
|
||||||
@ -1612,21 +1637,15 @@ NotificationFeature::Notify(JSContext* aCx, Status aStatus)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
Notification::RegisterFeature()
|
Notification::RegisterFeature()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mWorkerPrivate);
|
MOZ_ASSERT(mWorkerPrivate);
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
MOZ_ASSERT(!mFeature);
|
MOZ_ASSERT(!mFeature);
|
||||||
// Only calls to show() and close() should lead to AddFeature(), both of
|
|
||||||
// which come from JS. So we can assert that AddFeature() should succeed.
|
|
||||||
mFeature = MakeUnique<NotificationFeature>(this);
|
mFeature = MakeUnique<NotificationFeature>(this);
|
||||||
bool ok =
|
return mWorkerPrivate->AddFeature(mWorkerPrivate->GetJSContext(),
|
||||||
mWorkerPrivate->AddFeature(mWorkerPrivate->GetJSContext(),
|
mFeature.get());
|
||||||
mFeature.get());
|
|
||||||
if (!ok) {
|
|
||||||
MOZ_CRASH("AddFeature failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -34,8 +34,8 @@ namespace workers {
|
|||||||
class Notification;
|
class Notification;
|
||||||
class NotificationFeature final : public workers::WorkerFeature
|
class NotificationFeature final : public workers::WorkerFeature
|
||||||
{
|
{
|
||||||
// Held alive by Notification itself before feature is added, and only
|
// Since the feature is strongly held by a Notification, it is ok to hold
|
||||||
// released after feature is removed.
|
// a raw pointer here.
|
||||||
Notification* mNotification;
|
Notification* mNotification;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -47,7 +47,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notifications on workers introduce some liveness issues. The property we
|
* Notifications on workers introduce some lifetime issues. The property we
|
||||||
* are trying to satisfy is:
|
* are trying to satisfy is:
|
||||||
* Whenever a task is dispatched to the main thread to operate on
|
* Whenever a task is dispatched to the main thread to operate on
|
||||||
* a Notification, the Notification should be addrefed on the worker thread
|
* a Notification, the Notification should be addrefed on the worker thread
|
||||||
@ -69,7 +69,14 @@ public:
|
|||||||
* UI is still visible to the user. We handle this case with the following
|
* UI is still visible to the user. We handle this case with the following
|
||||||
* steps:
|
* steps:
|
||||||
* a) Close the notification. This is done by blocking the worker on the main
|
* a) Close the notification. This is done by blocking the worker on the main
|
||||||
* thread.
|
* thread. This ensures that there are no main thread holders when the worker
|
||||||
|
* resumes. This also deals with the case where Notify() runs on the worker
|
||||||
|
* before the observer has been created on the main thread. Even in such
|
||||||
|
* a situation, the CloseNotificationRunnable() will only run after the
|
||||||
|
* Show task that was previously queued. Since the show task is only queued
|
||||||
|
* once when the Notification is created, we can be sure that no new tasks
|
||||||
|
* will follow the Notify().
|
||||||
|
*
|
||||||
* b) Ask the observer to let go of its NotificationRef's underlying
|
* b) Ask the observer to let go of its NotificationRef's underlying
|
||||||
* Notification without proper cleanup since the feature will handle the
|
* Notification without proper cleanup since the feature will handle the
|
||||||
* release. This is only OK because every notification has only one
|
* release. This is only OK because every notification has only one
|
||||||
@ -206,7 +213,10 @@ public:
|
|||||||
MOZ_ASSERT(IsTargetThread());
|
MOZ_ASSERT(IsTargetThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialized on the worker thread, never unset, and always used in
|
||||||
|
// a read-only capacity. Used on any thread.
|
||||||
workers::WorkerPrivate* mWorkerPrivate;
|
workers::WorkerPrivate* mWorkerPrivate;
|
||||||
|
|
||||||
// Main thread only.
|
// Main thread only.
|
||||||
WorkerNotificationObserver* mObserver;
|
WorkerNotificationObserver* mObserver;
|
||||||
|
|
||||||
@ -215,9 +225,12 @@ public:
|
|||||||
// passes this on to the Notification itself via mTempRef so that
|
// passes this on to the Notification itself via mTempRef so that
|
||||||
// ShowInternal()/CloseInternal() may pass it along appropriately (or release
|
// ShowInternal()/CloseInternal() may pass it along appropriately (or release
|
||||||
// it).
|
// it).
|
||||||
|
//
|
||||||
|
// Main thread only.
|
||||||
UniquePtr<NotificationRef> mTempRef;
|
UniquePtr<NotificationRef> mTempRef;
|
||||||
|
|
||||||
void AddRefObject();
|
// Returns true if addref succeeded.
|
||||||
|
bool AddRefObject();
|
||||||
void ReleaseObject();
|
void ReleaseObject();
|
||||||
|
|
||||||
static NotificationPermission GetPermissionInternal(nsIPrincipal* aPrincipal,
|
static NotificationPermission GetPermissionInternal(nsIPrincipal* aPrincipal,
|
||||||
@ -311,12 +324,14 @@ private:
|
|||||||
return NS_IsMainThread() == !mWorkerPrivate;
|
return NS_IsMainThread() == !mWorkerPrivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterFeature();
|
bool RegisterFeature();
|
||||||
void UnregisterFeature();
|
void UnregisterFeature();
|
||||||
|
|
||||||
nsresult ResolveIconAndSoundURL(nsString&, nsString&);
|
nsresult ResolveIconAndSoundURL(nsString&, nsString&);
|
||||||
|
|
||||||
|
// Only used for Notifications on Workers, worker thread only.
|
||||||
UniquePtr<NotificationFeature> mFeature;
|
UniquePtr<NotificationFeature> mFeature;
|
||||||
|
// Target thread only.
|
||||||
uint32_t mTaskCount;
|
uint32_t mTaskCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user