Bug 1059194 - Trusted Hosted Apps, part 2: CSP infrastructure changes. r=sicking
authorVlatko Markovic <vlatko.markovic@sonymobile.com>
Tue, 16 Sep 2014 13:14:02 -0700
changeset 205573 07b8b2f1345daa5498db3d0860d950c855b9f4cc
parent 205572 140afb596080851f4dd80fed0d0fdf5b4066be09
child 205574 18ee130341c042e5ee2ee6a75f5958b51ab34433
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerssicking
bugs1059194
milestone35.0a1
Bug 1059194 - Trusted Hosted Apps, part 2: CSP infrastructure changes. r=sicking
b2g/app/b2g.js
content/base/src/nsDocument.cpp
dom/apps/AppsService.js
dom/apps/AppsServiceChild.jsm
dom/apps/AppsUtils.jsm
dom/apps/Webapps.jsm
dom/interfaces/apps/nsIAppsService.idl
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -393,16 +393,18 @@ pref("content.ime.strict_policy", true);
 // $ adb shell stop
 // $ adb shell setprop log.redirect-stdio true
 // $ adb shell start
 pref("browser.dom.window.dump.enabled", false);
 
 // Default Content Security Policy to apply to certified apps.
 // If you change this CSP, make sure to update the fast path in nsCSPService.cpp
 pref("security.apps.certified.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline' app://theme.gaiamobile.org");
+// Default Content Security Policy to apply to trusted apps.
+pref("security.apps.trusted.CSP.default", "default-src *; object-src 'none'; frame-src 'none'");
 
 // Temporarily force-enable GL compositing.  This is default-disabled
 // deep within the bowels of the widgetry system.  Remove me when GL
 // compositing isn't default disabled in widget/android.
 pref("layers.acceleration.force-enabled", true);
 
 // handle links targeting new windows
 // 1=current window/tab, 2=new window, 3=new tab in most recent window
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2758,30 +2758,34 @@ nsDocument::InitCSP(nsIChannel* aChannel
   }
   NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue);
   NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
 
   // Figure out if we need to apply an app default CSP or a CSP from an app manifest
   nsIPrincipal* principal = NodePrincipal();
 
   uint16_t appStatus = principal->GetAppStatus();
-  bool applyAppDefaultCSP = appStatus == nsIPrincipal::APP_STATUS_PRIVILEGED ||
-                            appStatus == nsIPrincipal::APP_STATUS_CERTIFIED;
+  bool applyAppDefaultCSP = false;
   bool applyAppManifestCSP = false;
 
   nsAutoString appManifestCSP;
+  nsAutoString appDefaultCSP;
   if (appStatus != nsIPrincipal::APP_STATUS_NOT_INSTALLED) {
     nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
     if (appsService) {
       uint32_t appId = 0;
       if (NS_SUCCEEDED(principal->GetAppId(&appId))) {
-        appsService->GetCSPByLocalId(appId, appManifestCSP);
+        appsService->GetManifestCSPByLocalId(appId, appManifestCSP);
         if (!appManifestCSP.IsEmpty()) {
           applyAppManifestCSP = true;
         }
+        appsService->GetDefaultCSPByLocalId(appId, appDefaultCSP);
+        if (!appDefaultCSP.IsEmpty()) {
+          applyAppDefaultCSP = true;
+        }
       }
     }
   }
 
   // If there's no CSP to apply, go ahead and return early
   if (!applyAppDefaultCSP &&
       !applyAppManifestCSP &&
       cspHeaderValue.IsEmpty() &&
@@ -2843,28 +2847,17 @@ nsDocument::InitCSP(nsIChannel* aChannel
   nsCOMPtr<nsIURI> selfURI;
   aChannel->GetURI(getter_AddRefs(selfURI));
 
   // Store the request context for violation reports
   csp->SetRequestContext(nullptr, nullptr, aChannel);
 
   // ----- if the doc is an app and we want a default CSP, apply it.
   if (applyAppDefaultCSP) {
-    nsAdoptingString appCSP;
-    if (appStatus ==  nsIPrincipal::APP_STATUS_PRIVILEGED) {
-      appCSP = Preferences::GetString("security.apps.privileged.CSP.default");
-      NS_ASSERTION(appCSP, "App, but no default CSP in security.apps.privileged.CSP.default");
-    } else if (appStatus == nsIPrincipal::APP_STATUS_CERTIFIED) {
-      appCSP = Preferences::GetString("security.apps.certified.CSP.default");
-      NS_ASSERTION(appCSP, "App, but no default CSP in security.apps.certified.CSP.default");
-    }
-
-    if (appCSP) {
-      csp->AppendPolicy(appCSP, false);
-    }
+    csp->AppendPolicy(appDefaultCSP, false);
   }
 
   // ----- if the doc is an app and specifies a CSP in its manifest, apply it.
   if (applyAppManifestCSP) {
     csp->AppendPolicy(appManifestCSP, false);
   }
 
   // ----- if there's a full-strength CSP header, apply it.
--- a/dom/apps/AppsService.js
+++ b/dom/apps/AppsService.js
@@ -25,19 +25,24 @@ function AppsService()
                     .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
   debug("inParent: " + this.inParent);
   Cu.import(this.inParent ? "resource://gre/modules/Webapps.jsm" :
                             "resource://gre/modules/AppsServiceChild.jsm");
 }
 
 AppsService.prototype = {
 
-  getCSPByLocalId: function getCSPByLocalId(localId) {
-    debug("GetCSPByLocalId( " + localId + " )");
-    return DOMApplicationRegistry.getCSPByLocalId(localId);
+  getManifestCSPByLocalId: function getCSPByLocalId(localId) {
+    debug("GetManifestCSPByLocalId( " + localId + " )");
+    return DOMApplicationRegistry.getManifestCSPByLocalId(localId);
+  },
+
+  getDefaultCSPByLocalId: function getCSPByLocalId(localId) {
+    debug("GetDefaultCSPByLocalId( " + localId + " )");
+    return DOMApplicationRegistry.getDefaultCSPByLocalId(localId);
   },
 
   getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
     debug("GetAppByManifestURL( " + aManifestURL + " )");
     return DOMApplicationRegistry.getAppByManifestURL(aManifestURL);
   },
 
   getManifestFor: function getManifestFor(aManifestURL) {
--- a/dom/apps/AppsServiceChild.jsm
+++ b/dom/apps/AppsServiceChild.jsm
@@ -360,19 +360,24 @@ this.DOMApplicationRegistry = {
     return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
   },
 
   getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
     debug("getAppLocalIdByManifestURL " + aManifestURL);
     return AppsUtils.getAppLocalIdByManifestURL(this.webapps, aManifestURL);
   },
 
-  getCSPByLocalId: function(aLocalId) {
-    debug("getCSPByLocalId:" + aLocalId);
-    return AppsUtils.getCSPByLocalId(this.webapps, aLocalId);
+  getManifestCSPByLocalId: function(aLocalId) {
+    debug("getManifestCSPByLocalId:" + aLocalId);
+    return AppsUtils.getManifestCSPByLocalId(this.webapps, aLocalId);
+  },
+
+  getDefaultCSPByLocalId: function(aLocalId) {
+    debug("getDefaultCSPByLocalId:" + aLocalId);
+    return AppsUtils.getDefaultCSPByLocalId(this.webapps, aLocalId);
   },
 
   getAppLocalIdByStoreId: function(aStoreId) {
     debug("getAppLocalIdByStoreId:" + aStoreId);
     return AppsUtils.getAppLocalIdByStoreId(this.webapps, aStoreId);
   },
 
   getAppByLocalId: function getAppByLocalId(aLocalId) {
--- a/dom/apps/AppsUtils.jsm
+++ b/dom/apps/AppsUtils.jsm
@@ -153,28 +153,55 @@ this.AppsUtils = {
       if (aApps[id].storeId == aStoreId) {
         return aApps[id].localId;
       }
     }
 
     return Ci.nsIScriptSecurityManager.NO_APP_ID;
   },
 
-  getCSPByLocalId: function getCSPByLocalId(aApps, aLocalId) {
-    debug("getCSPByLocalId " + aLocalId);
+  getManifestCSPByLocalId: function getManifestCSPByLocalId(aApps, aLocalId) {
+    debug("getManifestCSPByLocalId " + aLocalId);
     for (let id in aApps) {
       let app = aApps[id];
       if (app.localId == aLocalId) {
-	  return ( app.csp || "" );
+        return ( app.csp || "" );
       }
     }
 
     return "";
   },
 
+  getDefaultCSPByLocalId: function(aApps, aLocalId) {
+    debug("getDefaultCSPByLocalId " + aLocalId);
+    for (let id in aApps) {
+      let app = aApps[id];
+      if (app.localId == aLocalId) {
+        // Use the app kind and the app status to choose the right default CSP.
+        try {
+          switch (app.appStatus) {
+            case Ci.nsIPrincipal.APP_STATUS_CERTIFIED:
+              return Services.prefs.getCharPref("security.apps.certified.CSP.default");
+              break;
+            case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED:
+              return Services.prefs.getCharPref("security.apps.privileged.CSP.default");
+              break;
+            case Ci.nsIPrincipal.APP_STATUS_INSTALLED:
+              return app.kind == "hosted-trusted"
+                ? Services.prefs.getCharPref("security.apps.trusted.CSP.default")
+                : "";
+              break;
+          }
+        } catch(e) {}
+      }
+    }
+
+    return "default-src 'self'; object-src 'none'";
+  },
+
   getAppByLocalId: function getAppByLocalId(aApps, aLocalId) {
     debug("getAppByLocalId " + aLocalId);
     for (let id in aApps) {
       let app = aApps[id];
       if (app.localId == aLocalId) {
         return new mozIApplication(app);
       }
     }
--- a/dom/apps/Webapps.jsm
+++ b/dom/apps/Webapps.jsm
@@ -4182,19 +4182,24 @@ this.DOMApplicationRegistry = {
       throw new Error("NO_SUCH_APP");
     }
 
     app.manifest = ( yield this._readManifests([{ id: app.id }]) )[0].manifest;
 
     return app;
   }),
 
-  getCSPByLocalId: function(aLocalId) {
-    debug("getCSPByLocalId:" + aLocalId);
-    return AppsUtils.getCSPByLocalId(this.webapps, aLocalId);
+  getManifestCSPByLocalId: function(aLocalId) {
+    debug("getManifestCSPByLocalId:" + aLocalId);
+    return AppsUtils.getManifestCSPByLocalId(this.webapps, aLocalId);
+  },
+
+  getDefaultCSPByLocalId: function(aLocalId) {
+    debug("getDefaultCSPByLocalId:" + aLocalId);
+    return AppsUtils.getDefaultCSPByLocalId(this.webapps, aLocalId);
   },
 
   getAppLocalIdByStoreId: function(aStoreId) {
     debug("getAppLocalIdByStoreId:" + aStoreId);
     return AppsUtils.getAppLocalIdByStoreId(this.webapps, aStoreId);
   },
 
   getAppByLocalId: function(aLocalId) {
--- a/dom/interfaces/apps/nsIAppsService.idl
+++ b/dom/interfaces/apps/nsIAppsService.idl
@@ -11,17 +11,17 @@ interface nsIURI;
 #define APPS_SERVICE_CID { 0x05072afa, 0x92fe, 0x45bf, { 0xae, 0x22, 0x39, 0xb6, 0x9c, 0x11, 0x70, 0x58 } }
 #define APPS_SERVICE_CONTRACTID "@mozilla.org/AppsService;1"
 %}
 
 /*
  * This service allows accessing some DOMApplicationRegistry methods from
  * non-javascript code.
  */
-[scriptable, uuid(2e884bbe-7a3d-4b01-ad92-fcd65a449043)]
+[scriptable, uuid(76ced447-6f92-48fb-b4e6-690e4859bc7f)]
 interface nsIAppsService : nsISupports
 {
   mozIApplication getAppByManifestURL(in DOMString manifestURL);
 
   /**
    * Returns a Promise for the manifest for a given manifestURL.
    * This is only supported in the parent process: the promise will be rejected
    * in content processes.
@@ -42,19 +42,24 @@ interface nsIAppsService : nsISupports
   mozIApplication getAppByLocalId(in unsigned long localId);
 
   /**
    * Returns the manifest URL associated to this localId.
    */
   DOMString getManifestURLByLocalId(in unsigned long localId);
 
   /**
-   * Returns the CSP associated to this localId.
+   * Returns the manifest CSP associated to this localId.
    */
-  DOMString getCSPByLocalId(in unsigned long localId);
+  DOMString getManifestCSPByLocalId(in unsigned long localId);
+
+  /**
+   * Returns the default CSP associated to this localId.
+   */
+  DOMString getDefaultCSPByLocalId(in unsigned long localId);
 
   /**
    * Returns the basepath for core apps
    */
   DOMString getCoreAppsBasePath();
 
   /**
    * Returns the basepath for regular packaged apps