bug 1328964 add CycleCollectedJSContext::IsSystemCaller() to make ThreadsafeIsSystemCaller() safe for worklets r?baku draft
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 06 Apr 2018 18:53:25 +1200
changeset 780867 8069d1adb73660787c62993ddebf80c2f900cc32
parent 780866 58e4aeef280ca23466367c713f3669a74e468f6e
push id106145
push userktomlinson@mozilla.com
push dateThu, 12 Apr 2018 05:09:40 +0000
reviewersbaku
bugs1328964
milestone61.0a1
bug 1328964 add CycleCollectedJSContext::IsSystemCaller() to make ThreadsafeIsSystemCaller() safe for worklets r?baku MozReview-Commit-ID: Cg4OBbm5CwA
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/workers/RuntimeService.cpp
dom/worklet/WorkletThread.cpp
js/xpconnect/src/XPCJSContext.cpp
js/xpconnect/src/xpcprivate.h
xpcom/base/CycleCollectedJSContext.h
--- 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;