Bug 1576254 - Cut WorkerPrincipal over to a real object and implement isSystemOrAddonPrincipal r=baku
authorTom Ritter <tom@mozilla.com>
Fri, 04 Oct 2019 17:37:09 +0000
changeset 496389 2498e68e641cbac86bac59a54ffd8372e2a905ec
parent 496388 59f5758eb829c44389971429ac5d1857dae323b8
child 496390 7c7ccb6e9ce55f60a540d993bb83854b7f735d36
push id97215
push usertritter@mozilla.com
push dateFri, 04 Oct 2019 19:40:14 +0000
treeherderautoland@35dfc96baca1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1576254
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1576254 - Cut WorkerPrincipal over to a real object and implement isSystemOrAddonPrincipal r=baku Unlike WorkletPrincipal, a WorkerPrincipal had been a simple static object shared by all Workers. We never needed to consult it about an individual Worker before. Now we do. So we cut it over from a static object to individual objects for each Worker. We have an off main thread access problem for the Principal however, WorkerPrivate has a method UsesSystemPrincipal that returns a bool that was initialized from the Principal on the main thread. We copy that pattern and add a UsesAddonOrExpandedAddonPrincipal method that will be called by the isSystemOrAddonPrincipal method we must implement so we can inheirt from JSPrincipal. Differential Revision: https://phabricator.services.mozilla.com/D47476
dom/workers/Principal.cpp
dom/workers/Principal.h
dom/workers/RuntimeService.cpp
dom/workers/WorkerLoadInfo.cpp
dom/workers/WorkerLoadInfo.h
dom/workers/WorkerPrivate.h
dom/workers/WorkerScope.cpp
--- a/dom/workers/Principal.cpp
+++ b/dom/workers/Principal.cpp
@@ -8,42 +8,29 @@
 
 #include "jsapi.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 
 namespace mozilla {
 namespace dom {
 
-struct WorkerPrincipal final : public JSPrincipals {
-  bool write(JSContext* aCx, JSStructuredCloneWriter* aWriter) override {
-    return JS_WriteUint32Pair(aWriter, SCTAG_DOM_WORKER_PRINCIPAL, 0);
-  }
-};
-
-JSPrincipals* GetWorkerPrincipal() {
-  static WorkerPrincipal sPrincipal;
-
-  /*
-   * To make sure the the principals refcount is initialized to one, atomically
-   * increment it on every pass though this function. If we discover this wasn't
-   * the first time, decrement it again. This avoids the need for
-   * synchronization.
-   */
-  int32_t prevRefcount = sPrincipal.refcount++;
-  if (prevRefcount > 0) {
-    --sPrincipal.refcount;
-  } else {
-#ifdef DEBUG
-    sPrincipal.debugToken = workerinternals::kJSPrincipalsDebugToken;
-#endif
-  }
-
-  return &sPrincipal;
+WorkerPrincipal::WorkerPrincipal(bool aIsSystemOrAddonPrincipal)
+    : JSPrincipals(), mIsSystemOrAddonPrincipal(aIsSystemOrAddonPrincipal) {
+  setDebugToken(workerinternals::kJSPrincipalsDebugToken);
 }
 
-void DestroyWorkerPrincipals(JSPrincipals* aPrincipals) {
-  MOZ_ASSERT_UNREACHABLE(
-      "Worker principals refcount should never fall below one");
+WorkerPrincipal::~WorkerPrincipal() = default;
+
+bool WorkerPrincipal::write(JSContext* aCx, JSStructuredCloneWriter* aWriter) {
+  return JS_WriteUint32Pair(aWriter, SCTAG_DOM_WORKER_PRINCIPAL, 0);
+}
+
+bool WorkerPrincipal::isSystemOrAddonPrincipal() {
+  return mIsSystemOrAddonPrincipal;
+}
+
+void WorkerPrincipal::Destroy(JSPrincipals* aPrincipals) {
+  delete static_cast<WorkerPrincipal*>(aPrincipals);
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/workers/Principal.h
+++ b/dom/workers/Principal.h
@@ -7,16 +7,30 @@
 #ifndef mozilla_dom_workers_principal_h__
 #define mozilla_dom_workers_principal_h__
 
 #include "WorkerCommon.h"
 
 namespace mozilla {
 namespace dom {
 
-JSPrincipals* GetWorkerPrincipal();
+struct MOZ_HEAP_CLASS WorkerPrincipal final : public JSPrincipals {
+  explicit WorkerPrincipal(bool aIsSystemOrAddonPrincipal);
+
+  bool write(JSContext* aCx, JSStructuredCloneWriter* aWriter) override;
 
-void DestroyWorkerPrincipals(JSPrincipals* aPrincipals);
+  // We don't distinguish between System or Addon because the only use
+  // case for this right now doesn't need to. When you need to distinguish
+  // add a second bool.
+  bool isSystemOrAddonPrincipal() override;
+
+  // Callback for JS_InitDestroyPrincipalsCallback()
+  static void Destroy(JSPrincipals* aPrincipals);
+
+ private:
+  ~WorkerPrincipal();
+  bool mIsSystemOrAddonPrincipal;
+};
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif /* mozilla_dom_workers_principal_h__ */
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -960,17 +960,17 @@ class WorkerJSContext final : public moz
         WORKER_DEFAULT_NURSERY_SIZE);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     JSContext* cx = Context();
 
     js::SetPreserveWrapperCallback(cx, PreserveWrapper);
-    JS_InitDestroyPrincipalsCallback(cx, DestroyWorkerPrincipals);
+    JS_InitDestroyPrincipalsCallback(cx, WorkerPrincipal::Destroy);
     JS_SetWrapObjectCallbacks(cx, &WrapObjectCallbacks);
     if (mWorkerPrivate->IsDedicatedWorker()) {
       JS_SetFutexCanWait(cx);
     }
 
     return NS_OK;
   }
 
--- a/dom/workers/WorkerLoadInfo.cpp
+++ b/dom/workers/WorkerLoadInfo.cpp
@@ -84,31 +84,34 @@ WorkerLoadInfoData::WorkerLoadInfoData()
     : mLoadFlags(nsIRequest::LOAD_NORMAL),
       mWindowID(UINT64_MAX),
       mReferrerInfo(new ReferrerInfo(nullptr)),
       mFromWindow(false),
       mEvalAllowed(false),
       mReportCSPViolations(false),
       mXHRParamsAllowed(false),
       mPrincipalIsSystem(false),
+      mPrincipalIsAddonOrExpandedAddon(false),
       mWatchedByDevtools(false),
       mStorageAccess(StorageAccess::eDeny),
       mFirstPartyStorageAccessGranted(false),
       mServiceWorkersTestingInWindow(false),
       mSecureContext(eNotSet) {}
 
 nsresult WorkerLoadInfo::SetPrincipalsAndCSPOnMainThread(
     nsIPrincipal* aPrincipal, nsIPrincipal* aStoragePrincipal,
     nsILoadGroup* aLoadGroup, nsIContentSecurityPolicy* aCsp) {
   AssertIsOnMainThread();
   MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadGroup, aPrincipal));
 
   mPrincipal = aPrincipal;
   mStoragePrincipal = aStoragePrincipal;
   mPrincipalIsSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
+  mPrincipalIsAddonOrExpandedAddon =
+      aPrincipal->GetIsAddonOrExpandedAddonPrincipal();
 
   mCSP = aCsp;
 
   if (mCSP) {
     mCSP->GetAllowsEval(&mReportCSPViolations, &mEvalAllowed);
     mCSPInfo = new CSPInfo();
     nsresult rv = CSPToCSPInfo(aCsp, mCSPInfo);
     if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/workers/WorkerLoadInfo.h
+++ b/dom/workers/WorkerLoadInfo.h
@@ -121,16 +121,17 @@ struct WorkerLoadInfoData {
   uint64_t mWindowID;
 
   nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
   bool mFromWindow;
   bool mEvalAllowed;
   bool mReportCSPViolations;
   bool mXHRParamsAllowed;
   bool mPrincipalIsSystem;
+  bool mPrincipalIsAddonOrExpandedAddon;
   bool mWatchedByDevtools;
   StorageAccess mStorageAccess;
   bool mFirstPartyStorageAccessGranted;
   bool mServiceWorkersTestingInWindow;
   OriginAttributes mOriginAttributes;
 
   enum {
     eNotSet,
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -690,16 +690,19 @@ class WorkerPrivate : public RelativeTim
   const nsAString& Origin() const { return mLoadInfo.mOrigin; }
 
   nsILoadGroup* GetLoadGroup() const {
     AssertIsOnMainThread();
     return mLoadInfo.mLoadGroup;
   }
 
   bool UsesSystemPrincipal() const { return mLoadInfo.mPrincipalIsSystem; }
+  bool UsesAddonOrExpandedAddonPrincipal() const {
+    return mLoadInfo.mPrincipalIsAddonOrExpandedAddon;
+  }
 
   const mozilla::ipc::PrincipalInfo& GetPrincipalInfo() const {
     return *mLoadInfo.mPrincipalInfo;
   }
 
   const mozilla::ipc::PrincipalInfo& GetEffectiveStoragePrincipalInfo() const {
     return *mLoadInfo.mStoragePrincipalInfo;
   }
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -609,17 +609,20 @@ bool DedicatedWorkerGlobalScope::WrapGlo
   JS::RealmBehaviors& behaviors = options.behaviors();
   behaviors.setDiscardSource(discardSource)
       .extraWarningsOverride()
       .set(extraWarnings);
 
   xpc::SetPrefableRealmOptions(options);
 
   return DedicatedWorkerGlobalScope_Binding::Wrap(
-      aCx, this, this, options, GetWorkerPrincipal(), true, aReflector);
+      aCx, this, this, options,
+      new WorkerPrincipal(usesSystemPrincipal ||
+                          mWorkerPrivate->UsesAddonOrExpandedAddonPrincipal()),
+      true, aReflector);
 }
 
 void DedicatedWorkerGlobalScope::PostMessage(
     JSContext* aCx, JS::Handle<JS::Value> aMessage,
     const Sequence<JSObject*>& aTransferable, ErrorResult& aRv) {
   mWorkerPrivate->AssertIsOnWorkerThread();
   mWorkerPrivate->PostMessageToParent(aCx, aMessage, aTransferable, aRv);
 }
@@ -645,17 +648,20 @@ bool SharedWorkerGlobalScope::WrapGlobal
     JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
   mWorkerPrivate->AssertIsOnWorkerThread();
   MOZ_ASSERT(mWorkerPrivate->IsSharedWorker());
 
   JS::RealmOptions options;
   mWorkerPrivate->CopyJSRealmOptions(options);
 
   return SharedWorkerGlobalScope_Binding::Wrap(
-      aCx, this, this, options, GetWorkerPrincipal(), true, aReflector);
+      aCx, this, this, options,
+      new WorkerPrincipal(mWorkerPrivate->UsesSystemPrincipal() ||
+                          mWorkerPrivate->UsesAddonOrExpandedAddonPrincipal()),
+      true, aReflector);
 }
 
 void SharedWorkerGlobalScope::Close() {
   mWorkerPrivate->AssertIsOnWorkerThread();
   mWorkerPrivate->CloseInternal();
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope,
@@ -685,17 +691,20 @@ bool ServiceWorkerGlobalScope::WrapGloba
     JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
   mWorkerPrivate->AssertIsOnWorkerThread();
   MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
 
   JS::RealmOptions options;
   mWorkerPrivate->CopyJSRealmOptions(options);
 
   return ServiceWorkerGlobalScope_Binding::Wrap(
-      aCx, this, this, options, GetWorkerPrincipal(), true, aReflector);
+      aCx, this, this, options,
+      new WorkerPrincipal(mWorkerPrivate->UsesSystemPrincipal() ||
+                          mWorkerPrivate->UsesAddonOrExpandedAddonPrincipal()),
+      true, aReflector);
 }
 
 already_AddRefed<Clients> ServiceWorkerGlobalScope::GetClients() {
   if (!mClients) {
     mClients = new Clients(this);
   }
 
   RefPtr<Clients> ref = mClients;
@@ -936,17 +945,20 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEvent
 bool WorkerDebuggerGlobalScope::WrapGlobalObject(
     JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   JS::RealmOptions options;
   mWorkerPrivate->CopyJSRealmOptions(options);
 
   return WorkerDebuggerGlobalScope_Binding::Wrap(
-      aCx, this, this, options, GetWorkerPrincipal(), true, aReflector);
+      aCx, this, this, options,
+      new WorkerPrincipal(mWorkerPrivate->UsesSystemPrincipal() ||
+                          mWorkerPrivate->UsesAddonOrExpandedAddonPrincipal()),
+      true, aReflector);
 }
 
 void WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx,
                                           JS::MutableHandle<JSObject*> aGlobal,
                                           ErrorResult& aRv) {
   WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
   if (!scope) {
     aRv.Throw(NS_ERROR_FAILURE);