bug 1328964 add CycleCollectedJSContext::IsSystemCaller() to make ThreadsafeIsSystemCaller() safe for worklets r?baku
MozReview-Commit-ID: Cg4OBbm5CwA
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -58,17 +58,17 @@
#include "mozilla/dom/NodeBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/dom/Text.h"
#include "mozilla/dom/TouchEvent.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/XULCommandEvent.h"
-#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/Likely.h"
@@ -2374,21 +2374,20 @@ nsContentUtils::IsSystemCaller(JSContext
{
// Note that SubjectPrincipal() assumes we are in a compartment here.
return SubjectPrincipal(aCx) == sSystemPrincipal;
}
bool
nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx)
{
- if (NS_IsMainThread()) {
- return IsSystemCaller(aCx);
- }
-
- return GetWorkerPrivateFromContext(aCx)->UsesSystemPrincipal();
+ CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
+ MOZ_ASSERT(ccjscx->Context() == aCx);
+
+ return ccjscx->IsSystemCaller();
}
// static
bool
nsContentUtils::LookupBindingMember(JSContext* aCx, nsIContent *aContent,
JS::Handle<jsid> aId,
JS::MutableHandle<JS::PropertyDescriptor> aDesc)
{
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -224,17 +224,18 @@ public:
// 2) Bindings code or other code called directly from the JS engine.
//
// Use pretty much anywhere else is almost certainly wrong and should be
// replaced with [NeedsCallerType] annotations in bindings.
// Check whether the caller is system if you know you're on the main thread.
static bool IsSystemCaller(JSContext* aCx);
- // Check whether the caller is system if you might be on a worker thread.
+ // Check whether the caller is system if you might be on a worker or worklet
+ // thread.
static bool ThreadsafeIsSystemCaller(JSContext* aCx);
// In the traditional Gecko architecture, both C++ code and untrusted JS code
// needed to rely on the same XPCOM method/getter/setter to get work done.
// This required lots of security checks in the various exposed methods, which
// in turn created difficulty in determining whether the caller was script
// (whose access needed to be checked) and internal C++ platform code (whose
// access did not need to be checked). To address this problem, Gecko had a
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -1135,16 +1135,21 @@ public:
IsWorkerDebuggerSandbox(global));
microTaskQueue = &GetDebuggerMicroTaskQueue();
}
microTaskQueue->push(runnable.forget());
}
+ bool IsSystemCaller() const override
+ {
+ return mWorkerPrivate->UsesSystemPrincipal();
+ }
+
private:
WorkerPrivate* mWorkerPrivate;
};
class WorkerThreadPrimaryRunnable final : public Runnable
{
WorkerPrivate* mWorkerPrivate;
RefPtr<WorkerThread> mThread;
--- a/dom/worklet/WorkletThread.cpp
+++ b/dom/worklet/WorkletThread.cpp
@@ -225,16 +225,22 @@ public:
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
MOZ_ASSERT(global);
#endif
GetMicroTaskQueue().push(runnable.forget());
}
+ bool IsSystemCaller() const override
+ {
+ // Currently no support for special system worklet privileges.
+ return false;
+ }
+
private:
RefPtr<WorkletThread> mWorkletThread;
};
// This is the first runnable to be dispatched. It calls the RunEventLoop() so
// basically everything happens into this runnable. The reason behind this
// approach is that, when the Worklet is terminated, it must not have any JS in
// stack, but, because we have CC, nsIThread creates an AutoNoJSAPI object by
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -1252,8 +1252,14 @@ XPCJSContext::AfterProcessTask(uint32_t
CycleCollectedJSContext::AfterProcessTask(aNewRecursionDepth);
// Now that we are certain that the event is complete,
// we can flush any ongoing performance measurement.
js::FlushPerformanceMonitoring(Context());
mozilla::jsipc::AfterProcessTask();
}
+
+bool
+XPCJSContext::IsSystemCaller() const
+{
+ return nsContentUtils::IsSystemCaller(Context());
+}
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -410,16 +410,18 @@ public:
virtual void BeforeProcessTask(bool aMightBlock) override;
virtual void AfterProcessTask(uint32_t aNewRecursionDepth) override;
~XPCJSContext();
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
+ bool IsSystemCaller() const override;
+
AutoMarkingPtr** GetAutoRootsAdr() {return &mAutoRoots;}
nsresult GetPendingResult() { return mPendingResult; }
void SetPendingResult(nsresult rv) { mPendingResult = rv; }
PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory);
static void ActivityCallback(void* arg, bool active);
--- a/xpcom/base/CycleCollectedJSContext.h
+++ b/xpcom/base/CycleCollectedJSContext.h
@@ -234,16 +234,18 @@ public:
JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mUncaughtRejections;
// Promises in this list have previously been reported as rejected
// (because they were in the above list), but the rejection was handled
// in the last turn of the event loop.
JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mConsumedRejections;
nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
+ virtual bool IsSystemCaller() const = 0;
+
private:
// A primary context owns the mRuntime. Non-main-thread contexts should always
// be primary. On the main thread, the primary context should be the first one
// created and the last one destroyed. Non-primary contexts are used for
// cooperatively scheduled threads.
bool mIsPrimaryContext;
CycleCollectedJSRuntime* mRuntime;