Bug 1824753 [wpt PR 39216] - [FLEDGE] Add WPT test that FLEDGE is not allowed in...
[gecko.git] / dom / webscheduling / WebTaskScheduler.h
blobfcddd09d365bbbe3cacc28061f172b40fca182a0
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #ifndef mozilla_dom_WebTaskScheduler_h
9 #define mozilla_dom_WebTaskScheduler_h
11 #include "nsThreadUtils.h"
12 #include "nsPIDOMWindow.h"
13 #include "nsWrapperCache.h"
14 #include "nsClassHashtable.h"
16 #include "mozilla/dom/Promise.h"
17 #include "mozilla/dom/AbortFollower.h"
18 #include "mozilla/dom/TimeoutHandler.h"
19 #include "mozilla/dom/WebTaskSchedulingBinding.h"
21 namespace mozilla::dom {
22 class WebTask : public LinkedListElement<RefPtr<WebTask>>,
23 public AbortFollower,
24 public SupportsWeakPtr {
25 friend class WebTaskScheduler;
27 public:
28 MOZ_CAN_RUN_SCRIPT bool Run();
30 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
32 NS_DECL_CYCLE_COLLECTION_CLASS(WebTask)
33 WebTask(uint32_t aEnqueueOrder, SchedulerPostTaskCallback& aCallback,
34 Promise* aPromise)
35 : mEnqueueOrder(aEnqueueOrder),
36 mCallback(&aCallback),
37 mPromise(aPromise),
38 mHasScheduled(false) {}
40 void RunAbortAlgorithm() override;
42 bool HasScheduled() const { return mHasScheduled; }
44 uint32_t EnqueueOrder() const { return mEnqueueOrder; }
46 private:
47 void SetHasScheduled(bool aHasScheduled) { mHasScheduled = aHasScheduled; }
49 uint32_t mEnqueueOrder;
51 RefPtr<SchedulerPostTaskCallback> mCallback;
52 RefPtr<Promise> mPromise;
54 bool mHasScheduled;
56 ~WebTask() = default;
59 class WebTaskQueue {
60 public:
61 WebTaskQueue() = default;
63 TaskPriority Priority() const { return mPriority; }
64 void SetPriority(TaskPriority aNewPriority) { mPriority = aNewPriority; }
66 LinkedList<RefPtr<WebTask>>& Tasks() { return mTasks; }
68 void AddTask(WebTask* aTask) { mTasks.insertBack(aTask); }
70 // TODO: To optimize it, we could have the scheduled and unscheduled
71 // tasks stored separately.
72 WebTask* GetFirstScheduledTask() {
73 for (const auto& task : mTasks) {
74 if (task->HasScheduled()) {
75 return task;
78 return nullptr;
81 ~WebTaskQueue() { mTasks.clear(); }
83 private:
84 TaskPriority mPriority = TaskPriority::User_visible;
85 LinkedList<RefPtr<WebTask>> mTasks;
88 class WebTaskSchedulerMainThread;
89 class WebTaskSchedulerWorker;
91 class WebTaskScheduler : public nsWrapperCache, public SupportsWeakPtr {
92 friend class DelayedWebTaskHandler;
94 public:
95 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebTaskScheduler)
96 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebTaskScheduler)
98 static already_AddRefed<WebTaskSchedulerMainThread> CreateForMainThread(
99 nsGlobalWindowInner* aWindow);
101 static already_AddRefed<WebTaskSchedulerWorker> CreateForWorker(
102 WorkerPrivate* aWorkerPrivate);
104 explicit WebTaskScheduler(nsIGlobalObject* aParent);
106 already_AddRefed<Promise> PostTask(SchedulerPostTaskCallback& aCallback,
107 const SchedulerPostTaskOptions& aOptions);
109 nsIGlobalObject* GetParentObject() const { return mParent; }
111 virtual JSObject* WrapObject(JSContext* cx,
112 JS::Handle<JSObject*> aGivenProto) override;
114 WebTask* GetNextTask() const;
116 void Disconnect();
118 void RunTaskSignalPriorityChange(TaskSignal* aTaskSignal);
120 protected:
121 virtual ~WebTaskScheduler() = default;
122 nsCOMPtr<nsIGlobalObject> mParent;
124 uint32_t mNextEnqueueOrder;
126 private:
127 already_AddRefed<WebTask> CreateTask(
128 WebTaskQueue& aQueue, const Optional<OwningNonNull<AbortSignal>>& aSignal,
129 SchedulerPostTaskCallback& aCallback, Promise* aPromise);
131 bool QueueTask(WebTask* aTask);
133 WebTaskQueue& SelectTaskQueue(
134 const Optional<OwningNonNull<AbortSignal>>& aSignal,
135 const Optional<TaskPriority>& aPriority);
137 virtual nsresult SetTimeoutForDelayedTask(WebTask* aTask,
138 uint64_t aDelay) = 0;
139 virtual bool DispatchEventLoopRunnable() = 0;
141 nsClassHashtable<nsUint32HashKey, WebTaskQueue> mStaticPriorityTaskQueues;
142 nsClassHashtable<nsPtrHashKey<TaskSignal>, WebTaskQueue>
143 mDynamicPriorityTaskQueues;
146 class DelayedWebTaskHandler final : public TimeoutHandler {
147 public:
148 DelayedWebTaskHandler(JSContext* aCx, WebTaskScheduler* aScheduler,
149 WebTask* aTask)
150 : TimeoutHandler(aCx), mScheduler(aScheduler), mWebTask(aTask) {}
152 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
153 NS_DECL_CYCLE_COLLECTION_CLASS(DelayedWebTaskHandler)
155 MOZ_CAN_RUN_SCRIPT bool Call(const char* /* unused */) override {
156 if (mScheduler && mWebTask) {
157 MOZ_ASSERT(!mWebTask->HasScheduled());
158 if (!mScheduler->QueueTask(mWebTask)) {
159 return false;
162 return true;
165 private:
166 ~DelayedWebTaskHandler() override = default;
167 WeakPtr<WebTaskScheduler> mScheduler;
168 // WebTask gets added to WebTaskQueue, and WebTaskQueue keeps its alive.
169 WeakPtr<WebTask> mWebTask;
171 } // namespace mozilla::dom
172 #endif