Bug 1335890 - Factor out nsContentUtils::SubjectPrincipal version that takes JSContext draft 1335890-subjectPrincipal
authorTomislav Jovanovic <tomica@gmail.com>
Sun, 05 Feb 2017 23:19:26 +0100
changeset 479505 610fbe49d21aec2f777be120d6630fc0397a830f
parent 478994 f8d696a34c172ce8e118d5af0b0e7b7f4bb13105
child 544699 e61bb862ae032b7ec6a637d407ddaa7492bc7403
push id44270
push userbmo:tomica@gmail.com
push dateMon, 06 Feb 2017 20:06:42 +0000
bugs1335890
milestone54.0a1
Bug 1335890 - Factor out nsContentUtils::SubjectPrincipal version that takes JSContext MozReview-Commit-ID: CGRipgKUm7g
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -2079,21 +2079,18 @@ nsContentUtils::CanCallerAccess(nsPIDOMW
 bool
 nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAString& aPerm)
 {
   // Chrome gets access by default.
   if (IsSystemCaller(aCx)) {
     return true;
   }
 
-  JSCompartment* c = js::GetContextCompartment(aCx);
-  nsIPrincipal* p = nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
-
   // Otherwise, only allow if caller is an addon with the permission.
-  return BasePrincipal::Cast(p)->AddonHasPermission(aPerm);
+  return BasePrincipal::Cast(SubjectPrincipal(aCx))->AddonHasPermission(aPerm);
 }
 
 //static
 bool
 nsContentUtils::InProlog(nsINode *aNode)
 {
   NS_PRECONDITION(aNode, "missing node to nsContentUtils::InProlog");
 
@@ -2169,26 +2166,18 @@ nsContentUtils::IsCallerContentXBL()
     }
 
     return xpc::IsContentXBLScope(c);
 }
 
 bool
 nsContentUtils::IsSystemCaller(JSContext* aCx)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  // This is similar to what SubjectPrincipal() does, except we do in fact
-  // assume that we're in a compartment here; anyone who calls this function in
-  // situations where that's not the case is doing it wrong.
-  JSCompartment *compartment = js::GetContextCompartment(aCx);
-  MOZ_ASSERT(compartment);
-
-  JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
-  return nsJSPrincipals::get(principals) == sSystemPrincipal;
+  // 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);
   }
@@ -2774,16 +2763,32 @@ nsContentUtils::GenerateStateKey(nsICont
     }
   }
 
   return NS_OK;
 }
 
 // static
 nsIPrincipal*
+nsContentUtils::SubjectPrincipal(JSContext* aCx)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // As opposed to SubjectPrincipal(), we do in fact assume that
+  // we're in a compartment here; anyone who calls this function
+  // in situations where that's not the case is doing it wrong.
+  JSCompartment* compartment = js::GetContextCompartment(aCx);
+  MOZ_ASSERT(compartment);
+
+  JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
+  return nsJSPrincipals::get(principals);
+}
+
+// static
+nsIPrincipal*
 nsContentUtils::SubjectPrincipal()
 {
   MOZ_ASSERT(IsInitialized());
   MOZ_ASSERT(NS_IsMainThread());
   JSContext* cx = GetCurrentJSContext();
   if (!cx) {
     MOZ_CRASH("Accessing the Subject Principal without an AutoJSAPI on the stack is forbidden");
   }
@@ -2798,29 +2803,28 @@ nsContentUtils::SubjectPrincipal()
   //
   // So we want to return _something_ here - and definitely not the System
   // Principal, since that would make an AutoJSAPI a very dangerous thing to
   // instantiate.
   //
   // The natural thing to return is a null principal. Ideally, we'd return a
   // different null principal each time, to avoid any unexpected interactions
   // when the principal accidentally gets inherited somewhere. But
-  // GetSubjectPrincipal doesn't return strong references, so there's no way to
+  // SubjectPrincipal doesn't return strong references, so there's no way to
   // sanely manage the lifetime of multiple null principals.
   //
   // So we use a singleton null principal. To avoid it being accidentally
   // inherited and becoming a "real" subject or object principal, we do a
   // release-mode assert during compartment creation against using this
   // principal on an actual global.
   if (!compartment) {
     return sNullSubjectPrincipal;
   }
 
-  JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
-  return nsJSPrincipals::get(principals);
+  return SubjectPrincipal(cx);
 }
 
 // static
 nsIPrincipal*
 nsContentUtils::ObjectPrincipal(JSObject* aObj)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -540,16 +540,20 @@ public:
    * Get the cache security manager service. Can return null if the layout
    * module has been shut down.
    */
   static nsIScriptSecurityManager* GetSecurityManager()
   {
     return sSecurityManager;
   }
 
+  // Returns the subject principal from the JSContext. May only be called
+  // from the main thread and assumes an existing compartment.
+  static nsIPrincipal* SubjectPrincipal(JSContext* aCx);
+
   // Returns the subject principal. Guaranteed to return non-null. May only
   // be called when nsContentUtils is initialized.
   static nsIPrincipal* SubjectPrincipal();
 
   // Returns the prinipal of the given JS object. This may only be called on
   // the main thread for objects from the main thread's JSRuntime.
   static nsIPrincipal* ObjectPrincipal(JSObject* aObj);