Bug 1218039 - Add a nice interface for both C++ and JS to access the principal kind. r=gabor
authorBobby Holley <bobbyholley@gmail.com>
Fri, 23 Oct 2015 17:58:21 -0700
changeset 269627 4b90b038ae4c48abb77f065e3d63930533f00de9
parent 269626 567711c16ae83df237aa6bb90491051409cdc054
child 269628 924e0fbf9726575d31322e1e0a7fe3aae1a18744
push id29587
push usercbook@mozilla.com
push dateTue, 27 Oct 2015 09:56:28 +0000
treeherdermozilla-central@9a8f2342fb31 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor
bugs1218039
milestone44.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 1218039 - Add a nice interface for both C++ and JS to access the principal kind. r=gabor
caps/BasePrincipal.cpp
caps/BasePrincipal.h
caps/nsIPrincipal.idl
caps/nsNullPrincipal.cpp
caps/nsNullPrincipal.h
caps/nsPrincipal.h
caps/nsSystemPrincipal.h
caps/tests/unit/test_origin.js
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -335,19 +335,40 @@ BasePrincipal::GetCspJSON(nsAString& out
   if (!mCSP) {
     jsonPolicies.ToJSON(outCSPinJSON);
     return NS_OK;
   }
   return mCSP->ToJSON(outCSPinJSON);
 }
 
 NS_IMETHODIMP
-BasePrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
+BasePrincipal::GetIsNullPrincipal(bool* aResult)
+{
+  *aResult = Kind() == eNullPrincipal;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BasePrincipal::GetIsCodebasePrincipal(bool* aResult)
 {
-  *aIsNullPrincipal = false;
+  *aResult = Kind() == eCodebasePrincipal;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BasePrincipal::GetIsExpandedPrincipal(bool* aResult)
+{
+  *aResult = Kind() == eExpandedPrincipal;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BasePrincipal::GetIsSystemPrincipal(bool* aResult)
+{
+  *aResult = Kind() == eSystemPrincipal;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BasePrincipal::GetJarPrefix(nsACString& aJarPrefix)
 {
   mozilla::GetJarPrefix(mOriginAttributes.mAppId, mOriginAttributes.mInBrowser, aJarPrefix);
   return NS_OK;
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -142,17 +142,20 @@ public:
   NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
   NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
   NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
   NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) override;
-  NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) override;
+  NS_IMETHOD GetIsNullPrincipal(bool* aResult) override;
+  NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override;
+  NS_IMETHOD GetIsExpandedPrincipal(bool* aResult) override;
+  NS_IMETHOD GetIsSystemPrincipal(bool* aResult) override;
   NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix) final;
   NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
   NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
   NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) final;
   NS_IMETHOD GetAppId(uint32_t* aAppStatus) final;
   NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement) final;
   NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) final;
   NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
@@ -166,16 +169,25 @@ public:
   CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs);
   static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(const nsACString& aOrigin);
 
   const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
   uint32_t AppId() const { return mOriginAttributes.mAppId; }
   uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
   bool IsInBrowserElement() const { return mOriginAttributes.mInBrowser; }
 
+  enum PrincipalKind {
+    eNullPrincipal,
+    eCodebasePrincipal,
+    eExpandedPrincipal,
+    eSystemPrincipal
+  };
+
+  virtual PrincipalKind Kind() = 0;
+
 protected:
   virtual ~BasePrincipal();
 
   virtual nsresult GetOriginInternal(nsACString& aOrigin) = 0;
   virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0;
 
   // Internal, side-effect-free check to determine whether the concrete
   // principal would allow the load ignoring any common behavior implemented in
--- a/caps/nsIPrincipal.idl
+++ b/caps/nsIPrincipal.idl
@@ -15,17 +15,17 @@ struct JSPrincipals;
 
 interface nsIURI;
 interface nsIContentSecurityPolicy;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 [ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
 
-[scriptable, builtinclass, uuid(a083acd0-1ebf-4585-85ab-08cfdd9c96bd)]
+[scriptable, builtinclass, uuid(86e5fd29-dccb-4547-8918-f224005479a0)]
 interface nsIPrincipal : nsISerializable
 {
     /**
      * Returns whether the other principal is equivalent to this principal.
      * Principals are considered equal if they are the same principal, or
      * they have the same origin.
      */
     boolean equals(in nsIPrincipal other);
@@ -275,22 +275,37 @@ interface nsIPrincipal : nsISerializable
     /**
      * Returns true if this principal has an unknown appId. This shouldn't
      * generally be used. We only expose it due to not providing the correct
      * appId everywhere where we construct principals.
      */
     [infallible] readonly attribute boolean unknownAppId;
 
     /**
-     * Returns true iff this principal is a null principal (corresponding to an
+     * Returns true iff this is a null principal (corresponding to an
      * unknown, hence assumed minimally privileged, security context).
      */
     [infallible] readonly attribute boolean isNullPrincipal;
 
     /**
+     * Returns true iff this principal corresponds to a codebase origin.
+     */
+    [infallible] readonly attribute boolean isCodebasePrincipal;
+
+    /**
+     * Returns true iff this is an expanded principal.
+     */
+    [infallible] readonly attribute boolean isExpandedPrincipal;
+
+    /**
+     * Returns true iff this is the system principal.
+     */
+    [infallible] readonly attribute boolean isSystemPrincipal;
+
+    /**
      * Returns true if this principal's origin is recognized as being on the
      * whitelist of sites that can use the CSS Unprefixing Service.
      *
      * (This interface provides a trivial implementation, just returning false;
      * subclasses can implement something more complex as-needed.)
      */
     [noscript,notxpcom,nostdcall] bool IsOnCSSUnprefixingWhitelist();
 };
--- a/caps/nsNullPrincipal.cpp
+++ b/caps/nsNullPrincipal.cpp
@@ -120,23 +120,16 @@ nsNullPrincipal::MayLoadInternal(nsIURI*
       return true;
     }
   }
 
   return false;
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
-{
-  *aIsNullPrincipal = true;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsNullPrincipal::GetBaseDomain(nsACString& aBaseDomain)
 {
   // For a null principal, we use our unique uuid as the base domain.
   return mURI->GetPath(aBaseDomain);
 }
 
 /**
  * nsISerializable implementation
--- a/caps/nsNullPrincipal.h
+++ b/caps/nsNullPrincipal.h
@@ -39,31 +39,32 @@ public:
 
   NS_DECL_NSISERIALIZABLE
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
-  NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
   // Returns null on failure.
   static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIPrincipal *aInheritFrom);
 
   // Returns null on failure.
   static already_AddRefed<nsNullPrincipal>
     Create(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
 
   nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
 
   virtual void GetScriptLocation(nsACString &aStr) override;
 
+  PrincipalKind Kind() override { return eNullPrincipal; }
+
  protected:
   virtual ~nsNullPrincipal() {}
 
   bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override
   {
     return aOther == this;
   }
 
--- a/caps/nsPrincipal.h
+++ b/caps/nsPrincipal.h
@@ -44,16 +44,18 @@ public:
    */
   static nsresult GetOriginForURI(nsIURI* aURI, nsACString& aOrigin);
 
   /**
    * Called at startup to setup static data, e.g. about:config pref-observers.
    */
   static void InitializeStatics();
 
+  PrincipalKind Kind() override { return eCodebasePrincipal; }
+
   nsCOMPtr<nsIURI> mDomain;
   nsCOMPtr<nsIURI> mCodebase;
   // If mCodebaseImmutable is true, mCodebase is non-null and immutable
   bool mCodebaseImmutable;
   bool mDomainImmutable;
   bool mInitialized;
   mozilla::Maybe<bool> mIsOnCSSUnprefixingWhitelist; // Lazily-computed
 
@@ -78,16 +80,18 @@ public:
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   virtual bool IsOnCSSUnprefixingWhitelist() override;
   virtual void GetScriptLocation(nsACString &aStr) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
+  PrincipalKind Kind() override { return eExpandedPrincipal; }
+
 protected:
   virtual ~nsExpandedPrincipal();
 
   bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override;
   bool MayLoadInternal(nsIURI* aURI) override;
 
 private:
   nsTArray< nsCOMPtr<nsIPrincipal> > mPrincipals;
--- a/caps/nsSystemPrincipal.h
+++ b/caps/nsSystemPrincipal.h
@@ -45,11 +45,13 @@ protected:
   {
     return true;
   }
 
   bool MayLoadInternal(nsIURI* aURI) override
   {
     return true;
   }
+
+  PrincipalKind Kind() override { return eSystemPrincipal; }
 };
 
 #endif // nsSystemPrincipal_h__
--- a/caps/tests/unit/test_origin.js
+++ b/caps/tests/unit/test_origin.js
@@ -157,9 +157,21 @@ function run_test() {
   checkCrossOrigin(exampleOrg_addon, exampleOrg);
   checkCrossOrigin(exampleOrg_userContext, exampleOrg);
   checkCrossOrigin(exampleOrg_userContextAddon, exampleOrg);
   checkCrossOrigin(exampleOrg_userContext, exampleOrg_userContextAddon);
   checkCrossOrigin(exampleOrg_userContext, exampleOrg_userContextApp);
   checkCrossOrigin(exampleOrg_signedPkg, exampleOrg);
   checkCrossOrigin(exampleOrg_signedPkg, exampleOrg_signedPkg_browser);
   checkCrossOrigin(exampleOrg_signedPkg, exampleOrg_signedPkg_another);
+
+  // Check Principal kinds.
+  function checkKind(prin, kind) {
+    do_check_eq(prin.isNullPrincipal, kind == 'nullPrincipal');
+    do_check_eq(prin.isCodebasePrincipal, kind == 'codebasePrincipal');
+    do_check_eq(prin.isExpandedPrincipal, kind == 'expandedPrincipal');
+    do_check_eq(prin.isSystemPrincipal, kind == 'systemPrincipal');
+  }
+  checkKind(ssm.createNullPrincipal({}), 'nullPrincipal');
+  checkKind(ssm.createCodebasePrincipal(makeURI('http://www.example.com'), {}), 'codebasePrincipal');
+  checkKind(ssm.createExpandedPrincipal([ssm.createCodebasePrincipal(makeURI('http://www.example.com'), {})]), 'expandedPrincipal');
+  checkKind(ssm.getSystemPrincipal(), 'systemPrincipal');
 }