Bug 663570 - MetaCSP Part 2: Principal changes (r=bz)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Sat, 14 Nov 2015 19:28:23 -0800
changeset 308960 7939f4d62b7876f5b44411c9ee60547d832b88a5
parent 308959 632197cb15891288551963bd8330fd17774e8e48
child 308961 0f1a64890d9501cd6b1d5be6156157f553c59b87
push id7543
push userpehrsons@gmail.com
push dateMon, 16 Nov 2015 02:58:32 +0000
reviewersbz
bugs663570
milestone45.0a1
Bug 663570 - MetaCSP Part 2: Principal changes (r=bz)
caps/BasePrincipal.cpp
caps/BasePrincipal.h
caps/nsIPrincipal.idl
caps/nsSystemPrincipal.cpp
caps/nsSystemPrincipal.h
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -312,26 +312,42 @@ BasePrincipal::GetCsp(nsIContentSecurity
 {
   NS_IF_ADDREF(*aCsp = mCSP);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
 {
-  // If CSP was already set, it should not be destroyed!  Instead, it should
-  // get set anew when a new principal is created.
-  if (mCSP)
+  if (mCSP) {
     return NS_ERROR_ALREADY_INITIALIZED;
+  }
 
   mCSP = aCsp;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
+{
+  NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BasePrincipal::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP)
+{
+  if (mPreloadCSP) {
+    return NS_ERROR_ALREADY_INITIALIZED;
+  }
+  mPreloadCSP = aPreloadCSP;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 BasePrincipal::GetCspJSON(nsAString& outCSPinJSON)
 {
   outCSPinJSON.Truncate();
   dom::CSPPolicies jsonPolicies;
 
   if (!mCSP) {
     jsonPolicies.ToJSON(outCSPinJSON);
     return NS_OK;
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -141,16 +141,18 @@ public:
   NS_IMETHOD GetOriginNoSuffix(nsACString& aOrigin) final;
   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 GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
+  NS_IMETHOD SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP) override;
   NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) 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;
@@ -195,14 +197,15 @@ protected:
   virtual bool MayLoadInternal(nsIURI* aURI) = 0;
   friend class ::nsExpandedPrincipal;
 
   // Helper to check whether this principal is associated with an addon that
   // allows unprivileged code to load aURI.
   bool AddonAllowsLoad(nsIURI* aURI);
 
   nsCOMPtr<nsIContentSecurityPolicy> mCSP;
+  nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
   OriginAttributes mOriginAttributes;
 };
 
 } // namespace mozilla
 
 #endif /* mozilla_BasePrincipal_h */
--- 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(86e5fd29-dccb-4547-8918-f224005479a0)]
+[scriptable, builtinclass, uuid(188fc4a2-3157-4956-a7a2-d674991770da)]
 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);
@@ -127,20 +127,40 @@ interface nsIPrincipal : nsISerializable
      *                                   loader.
      * @throws NS_ERROR_DOM_BAD_URI if the load is not allowed.
      */
     void checkMayLoad(in nsIURI uri, in boolean report,
                       in boolean allowIfInheritsPrincipal);
 
     /**
      * A Content Security Policy associated with this principal.
+     *
+     * Please note that if a csp was already set on the
+     * principal, then it should not be destroyed! Instead, the
+     * current csp should be quried and extended by
+     * calling AppendPolicy() on it.
      */
     [noscript] attribute nsIContentSecurityPolicy csp;
 
     /**
+     * A speculative Content Security Policy associated with this
+     * principal. Set during speculative loading (preloading) and
+     * used *only* for preloads.
+     *
+     * If you want to query the CSP associated with that principal,
+     * then this is *not* what you want. Instead query 'csp'.
+     * 
+     * Please note that if a preloadCSP was already set on the
+     * principal, then it should not be destroyed! Instead, the
+     * current preloadCSP should be quried and extended by
+     * calling AppendPolicy() on it.
+     */
+    [noscript] attribute nsIContentSecurityPolicy preloadCsp;
+
+    /**
      * The CSP of the principal in JSON notation.
      * Note, that the CSP itself is not exposed to JS, but script
      * should be able to obtain a JSON representation of the CSP.
      */
     readonly attribute AString cspJSON;
 
     /**
      * Returns the jar prefix of the principal.
--- a/caps/nsSystemPrincipal.cpp
+++ b/caps/nsSystemPrincipal.cpp
@@ -67,17 +67,31 @@ nsSystemPrincipal::GetCsp(nsIContentSecu
 {
   *aCsp = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
 {
-  // CSP on a null principal makes no sense
+  // CSP on a system principal makes no sense
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSystemPrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
+{
+  *aPreloadCSP = nullptr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSystemPrincipal::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP)
+{
+  // CSP on a system principal makes no sense
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSystemPrincipal::GetDomain(nsIURI** aDomain)
 {
     *aDomain = nullptr;
     return NS_OK;
--- a/caps/nsSystemPrincipal.h
+++ b/caps/nsSystemPrincipal.h
@@ -26,16 +26,18 @@ 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 GetCsp(nsIContentSecurityPolicy** aCsp) override;
   NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
+  NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
+  NS_IMETHOD SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
   nsSystemPrincipal() {}
 
   virtual void GetScriptLocation(nsACString &aStr) override;
 
 protected: