Skip to content

Commit

Permalink
Bug 1725734 - Basic Web Locks implementation r=smaug,asuth
Browse files Browse the repository at this point in the history
  • Loading branch information
saschanaz committed Aug 18, 2021
1 parent 0476c7b commit a5e87a1
Show file tree
Hide file tree
Showing 36 changed files with 671 additions and 1,118 deletions.
11 changes: 11 additions & 0 deletions dom/base/Navigator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "mozilla/dom/MediaSession.h"
#include "mozilla/dom/WakeLock.h"
#include "mozilla/dom/power/PowerManagerService.h"
#include "mozilla/dom/LockManager.h"
#include "mozilla/dom/MIDIAccessManager.h"
#include "mozilla/dom/MIDIOptionsBinding.h"
#include "mozilla/dom/Permissions.h"
Expand Down Expand Up @@ -157,6 +158,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSession)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAddonManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebGpu)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocks)

NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
Expand Down Expand Up @@ -238,6 +240,8 @@ void Navigator::Invalidate() {

mWebGpu = nullptr;

mLocks = nullptr;

mSharePromise = nullptr;
}

Expand Down Expand Up @@ -2111,6 +2115,13 @@ webgpu::Instance* Navigator::Gpu() {
return mWebGpu;
}

dom::LockManager* Navigator::Locks() {
if (!mLocks) {
mLocks = new dom::LockManager(GetWindow()->AsGlobal());
}
return mLocks;
}

/* static */
bool Navigator::Webdriver() {
#ifdef ENABLE_WEBDRIVER
Expand Down
7 changes: 4 additions & 3 deletions dom/base/Navigator.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ServiceWorkerContainer;
class DOMRequest;
class CredentialsContainer;
class Clipboard;
class LockManager;
} // namespace dom
namespace webgpu {
class Instance;
Expand All @@ -52,8 +53,7 @@ class Instance;
// Navigator: Script "navigator" object
//*****************************************************************************

namespace mozilla {
namespace dom {
namespace mozilla::dom {

class Permissions;

Expand Down Expand Up @@ -206,6 +206,7 @@ class Navigator final : public nsISupports, public nsWrapperCache {
mozilla::dom::CredentialsContainer* Credentials();
dom::Clipboard* Clipboard();
webgpu::Instance* Gpu();
dom::LockManager* Locks();

static bool Webdriver();

Expand Down Expand Up @@ -285,9 +286,9 @@ class Navigator final : public nsISupports, public nsWrapperCache {
RefPtr<AddonManager> mAddonManager;
RefPtr<webgpu::Instance> mWebGpu;
RefPtr<Promise> mSharePromise; // Web Share API related
RefPtr<dom::LockManager> mLocks;
};

} // namespace dom
} // namespace mozilla

#endif // mozilla_dom_Navigator_h
63 changes: 63 additions & 0 deletions dom/locks/Lock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "mozilla/dom/Lock.h"
#include "mozilla/dom/LockBinding.h"
#include "mozilla/dom/LockManager.h"
#include "mozilla/dom/Promise.h"

namespace mozilla::dom {

NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Lock, mOwner, mLockManager,
mWaitingPromise, mReleasedPromise)
NS_IMPL_CYCLE_COLLECTING_ADDREF(Lock)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Lock)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Lock)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

Lock::Lock(nsIGlobalObject* aGlobal, const RefPtr<LockManager>& aLockManager,
const nsString& aName, LockMode aMode,
const RefPtr<Promise>& aReleasedPromise, ErrorResult& aRv)
: mOwner(aGlobal),
mLockManager(aLockManager),
mName(aName),
mMode(aMode),
mWaitingPromise(Promise::Create(aGlobal, aRv)),
mReleasedPromise(aReleasedPromise) {
MOZ_ASSERT(aLockManager);
MOZ_ASSERT(aReleasedPromise);
}

JSObject* Lock::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
return Lock_Binding::Wrap(aCx, this, aGivenProto);
}

void Lock::GetName(nsString& aRetVal) const { aRetVal = mName; }

LockMode Lock::Mode() const { return mMode; }

Promise& Lock::GetWaitingPromise() {
MOZ_ASSERT(mWaitingPromise);
return *mWaitingPromise;
}

void Lock::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) {
RefPtr<Lock> pin = this;
// decrements the refcount, may delete this
mLockManager->ReleaseHeldLock(this);
mReleasedPromise->MaybeResolve(aValue);
}

void Lock::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) {
RefPtr<Lock> pin = this;
// decrements the refcount, may delete this
mLockManager->ReleaseHeldLock(this);
mReleasedPromise->MaybeReject(aValue);
}

} // namespace mozilla::dom
75 changes: 75 additions & 0 deletions dom/locks/Lock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */

#ifndef mozilla_dom_Lock_h
#define mozilla_dom_Lock_h

#include "js/TypeDecls.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/LockManagerBinding.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"

namespace mozilla::dom {

class LockManager;

class Lock final : public PromiseNativeHandler, public nsWrapperCache {
friend class LockManager;

public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Lock)

Lock(nsIGlobalObject* aGlobal, const RefPtr<LockManager>& aLockManager,
const nsString& aName, LockMode aMode,
const RefPtr<Promise>& aReleasedPromise, ErrorResult& aRv);

bool operator==(const Lock& aOther) const {
// This operator is needed to remove released locks from the queue.
// This assumes each lock has a unique promise
MOZ_ASSERT(mReleasedPromise && aOther.mReleasedPromise,
"Promises are null when locks are unreleased??");
return mReleasedPromise == aOther.mReleasedPromise;
}

protected:
~Lock() = default;

public:
nsIGlobalObject* GetParentObject() const { return mOwner; };

JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;

void GetName(nsString& aRetVal) const;

LockMode Mode() const;

Promise& GetWaitingPromise();

// PromiseNativeHandler
virtual void ResolvedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue) override;
virtual void RejectedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue) override;

private:
nsCOMPtr<nsIGlobalObject> mOwner;
RefPtr<LockManager> mLockManager;

nsString mName;
LockMode mMode;
RefPtr<Promise> mWaitingPromise;
RefPtr<Promise> mReleasedPromise;
};

} // namespace mozilla::dom

#endif // mozilla_dom_Lock_h
Loading

0 comments on commit a5e87a1

Please sign in to comment.