Bug 1165162 - Add nsIPrincipal::cookieJar. r=sicking
authorBobby Holley <bobbyholley@gmail.com>
Mon, 18 May 2015 22:00:07 -0700
changeset 265904 e44ba0c0744aa9ecd6568d462f6d0522f53d50ca
parent 265903 cb2c0a02352edbe4103e32865e7d66c0f83c64b7
child 265905 eabe83ede1e3cd132eaf049ea5f53ce927c0b19f
push id2189
push useratolfsen@mozilla.com
push dateThu, 21 May 2015 13:24:13 +0000
reviewerssicking
bugs1165162
milestone41.0a1
Bug 1165162 - Add nsIPrincipal::cookieJar. r=sicking
caps/BasePrincipal.cpp
caps/BasePrincipal.h
caps/nsIPrincipal.idl
caps/tests/unit/test_origin.js
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -156,16 +156,25 @@ BasePrincipal::GetOriginAttributes(JSCon
 NS_IMETHODIMP
 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes)
 {
   mOriginAttributes.CreateSuffix(aOriginAttributes);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+BasePrincipal::GetCookieJar(nsACString& aCookieJar)
+{
+  // We just forward to .jarPrefix for now, which is a nice compact
+  // stringification of the (appId, inBrowser) tuple. This will eventaully be
+  // swapped out for an origin attribute - see the comment in nsIPrincipal.idl.
+  return GetJarPrefix(aCookieJar);
+}
+
+NS_IMETHODIMP
 BasePrincipal::GetAppStatus(uint16_t* aAppStatus)
 {
   if (AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
     NS_WARNING("Asking for app status on a principal with an unknown app id");
     *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
     return NS_OK;
   }
 
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -69,16 +69,17 @@ public:
   NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
   NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
   NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) 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 GetCookieJar(nsACString& aCookieJar) 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;
 
   virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
 
   static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
--- 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(147839d5-e799-4280-831a-dd45946385f9)]
+[scriptable, builtinclass, uuid(749f21f5-8ade-4d0b-a590-2b1d18e890d5)]
 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);
@@ -193,16 +193,40 @@ interface nsIPrincipal : nsISerializable
      * special requirements must inspect and compare .originSuffix manually.
      *
      * originsuffix are intended to be a replacement for jarPrefix, which will
      * eventually be removed.
      */
     readonly attribute AUTF8String originSuffix;
 
     /**
+     * Opaque string token representing the "cookie jar" associated with this
+     * principal. Cookie jars are intended to be a tag associated with persistent
+     * data (like cookies, localStorage data, etc) such that all data associated
+     * with a given cookie jar can be quickly located and (for example) deleted.
+     * Code from many origins may share a given cookie jar, so callers still need
+     * to consult .origin (or equivalent) to compartmentalize data - the cookie
+     * jar should _only_ be used as a tag in the manner described above.
+     *
+     * If two principals are in different cookie jars, they must be cross-origin.
+     * As such, the information making up the cookie jar token must be contained
+     * in the originAttributes (i.e. cookieJar must be a function of / derivable
+     * from originAttributes). Long term, the intention is for the cookie jar
+     * identifier to simply be an origin attribute. But we don't have that
+     * attribute yet, and we also need to concatenate the appId and inBrowser
+     * attributes until those go away.
+     *
+     * This getter is designed to hide these details from consumers so that they
+     * don't need to be updated when we swap out the implementation. For that
+     * reason, callers should treat the string as opaque and not rely on the
+     * current format.
+     */
+    readonly attribute ACString cookieJar;
+
+    /**
      * The base domain of the codebase URI to which this principal pertains
      * (generally the document URI), handling null principals and
      * non-hierarchical schemes correctly.
      */
     readonly attribute ACString baseDomain;
 
     const short APP_STATUS_NOT_INSTALLED = 0;
     const short APP_STATUS_INSTALLED     = 1;
--- a/caps/tests/unit/test_origin.js
+++ b/caps/tests/unit/test_origin.js
@@ -8,16 +8,19 @@ function makeURI(uri) { return Services.
 
 function checkCrossOrigin(a, b) {
   do_check_false(a.equals(b));
   do_check_false(a.equalsConsideringDomain(b));
   do_check_false(a.subsumes(b));
   do_check_false(a.subsumesConsideringDomain(b));
   do_check_false(b.subsumes(a));
   do_check_false(b.subsumesConsideringDomain(a));
+  do_check_eq(a.cookieJar === b.cookieJar,
+              a.originAttributes.appId == b.originAttributes.appId &&
+              a.originAttributes.inBrowser == b.originAttributes.inBrowser);
 }
 
 function checkOriginAttributes(prin, appId, inBrowser, suffix) {
   do_check_eq(prin.originAttributes.appId, appId || 0);
   do_check_eq(prin.originAttributes.inBrowser, inBrowser || false);
   do_check_eq(prin.originSuffix, suffix || '');
 }