Bug 813995 - Check device storage permissions in parent process. r=bent a=blocking-basecamp
authorDoug Turner <dougt@dougt.org>
Thu, 29 Nov 2012 21:41:40 -0800
changeset 114579 0690146190f1f37fdd414e4a6d8b891c21614532
parent 114578 a6b60491669479843bf270cf79cea8bd2af03f49
child 114580 2cf359411d7dcaa3acff6ff2755e42933908448d
push id23926
push userryanvm@gmail.com
push dateSat, 01 Dec 2012 15:27:30 +0000
treeherdermozilla-central@ecdf0e332f17 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent, blocking-basecamp
bugs813995
milestone20.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 813995 - Check device storage permissions in parent process. r=bent a=blocking-basecamp
dom/devicestorage/DeviceStorage.h
dom/devicestorage/DeviceStorageRequestParent.cpp
dom/devicestorage/DeviceStorageRequestParent.h
dom/ipc/ContentParent.cpp
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -41,18 +41,18 @@ private:
   nsresult GetInternal(const JS::Value & aName,
                        JSContext* aCx,
                        nsIDOMDOMRequest** aRetval,
                        bool aEditable);
 
   nsresult EnumerateInternal(const JS::Value & aName,
                              const JS::Value & aOptions,
                              JSContext* aCx,
-                             uint8_t aArgc, 
-                             bool aEditable, 
+                             uint8_t aArgc,
+                             bool aEditable,
                              nsIDOMDeviceStorageCursor** aRetval);
 
   nsString mStorageType;
   nsCOMPtr<nsIFile> mRootDirectory;
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
 
   bool mIsWatchingFile;
--- a/dom/devicestorage/DeviceStorageRequestParent.cpp
+++ b/dom/devicestorage/DeviceStorageRequestParent.cpp
@@ -6,31 +6,38 @@
 #include "DeviceStorageRequestParent.h"
 #include "nsDOMFile.h"
 #include "nsIMIMEService.h"
 #include "nsCExternalHandlerService.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "ContentParent.h"
 #include "nsProxyRelease.h"
+#include "AppProcessPermissions.h"
+#include "mozilla/Preferences.h"
 
 namespace mozilla {
 namespace dom {
 namespace devicestorage {
 
 DeviceStorageRequestParent::DeviceStorageRequestParent(const DeviceStorageParams& aParams)
-  : mMutex("DeviceStorageRequestParent::mMutex")
+  : mParams(aParams)
+  , mMutex("DeviceStorageRequestParent::mMutex")
   , mActorDestoryed(false)
 {
   MOZ_COUNT_CTOR(DeviceStorageRequestParent);
+}
 
-  switch (aParams.type()) {
+void
+DeviceStorageRequestParent::Dispatch()
+{
+  switch (mParams.type()) {
     case DeviceStorageParams::TDeviceStorageAddParams:
     {
-      DeviceStorageAddParams p = aParams;
+      DeviceStorageAddParams p = mParams;
 
       nsCOMPtr<nsIFile> f;
       NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
 
       nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
 
       BlobParent* bp = static_cast<BlobParent*>(p.blobParent());
       nsCOMPtr<nsIDOMBlob> blob = bp->GetBlob();
@@ -43,66 +50,66 @@ DeviceStorageRequestParent::DeviceStorag
       nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       NS_ASSERTION(target, "Must have stream transport service");
       target->Dispatch(r, NS_DISPATCH_NORMAL);
       break;
     }
 
     case DeviceStorageParams::TDeviceStorageGetParams:
     {
-      DeviceStorageGetParams p = aParams;
+      DeviceStorageGetParams p = mParams;
 
       nsCOMPtr<nsIFile> f;
       NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
 
       nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
       dsf->SetPath(p.name());
       nsRefPtr<CancelableRunnable> r = new ReadFileEvent(this, dsf);
 
       nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       NS_ASSERTION(target, "Must have stream transport service");
       target->Dispatch(r, NS_DISPATCH_NORMAL);
       break;
     }
 
     case DeviceStorageParams::TDeviceStorageDeleteParams:
     {
-      DeviceStorageDeleteParams p = aParams;
+      DeviceStorageDeleteParams p = mParams;
 
       nsCOMPtr<nsIFile> f;
       NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
 
       nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
       nsRefPtr<CancelableRunnable> r = new DeleteFileEvent(this, dsf);
 
       nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       NS_ASSERTION(target, "Must have stream transport service");
       target->Dispatch(r, NS_DISPATCH_NORMAL);
       break;
     }
 
     case DeviceStorageParams::TDeviceStorageStatParams:
     {
-      DeviceStorageStatParams p = aParams;
+      DeviceStorageStatParams p = mParams;
 
       nsCOMPtr<nsIFile> f;
       NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
 
       nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
       nsRefPtr<StatFileEvent> r = new StatFileEvent(this, dsf);
 
       nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       NS_ASSERTION(target, "Must have stream transport service");
       target->Dispatch(r, NS_DISPATCH_NORMAL);
       break;
     }
 
     case DeviceStorageParams::TDeviceStorageEnumerationParams:
     {
-      DeviceStorageEnumerationParams p = aParams;
+      DeviceStorageEnumerationParams p = mParams;
 
       nsCOMPtr<nsIFile> f;
       NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
 
       nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
       nsRefPtr<CancelableRunnable> r = new EnumerateFileEvent(this, dsf, p.since());
 
       nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@@ -113,16 +120,104 @@ DeviceStorageRequestParent::DeviceStorag
     default:
     {
       NS_RUNTIMEABORT("not reached");
       break;
     }
   }
 }
 
+bool
+DeviceStorageRequestParent::EnsureRequiredPermissions(mozilla::dom::ContentParent* aParent)
+{
+  if (mozilla::Preferences::GetBool("device.storage.testing", false)) {
+    return true;
+  }
+
+  nsString type;
+  DeviceStorageRequestType requestType;
+
+  switch (mParams.type())
+  {
+    case DeviceStorageParams::TDeviceStorageAddParams:
+    {
+      DeviceStorageAddParams p = mParams;
+      type = p.type();
+      requestType = DEVICE_STORAGE_REQUEST_CREATE;
+      break;
+    }
+
+    case DeviceStorageParams::TDeviceStorageGetParams:
+    {
+      DeviceStorageGetParams p = mParams;
+      type = p.type();
+      requestType = DEVICE_STORAGE_REQUEST_READ;
+      break;
+    }
+
+    case DeviceStorageParams::TDeviceStorageDeleteParams:
+    {
+      DeviceStorageDeleteParams p = mParams;
+      type = p.type();
+      requestType = DEVICE_STORAGE_REQUEST_DELETE;
+      break;
+    }
+
+    case DeviceStorageParams::TDeviceStorageStatParams:
+    {
+      DeviceStorageStatParams p = mParams;
+      type = p.type();
+      requestType = DEVICE_STORAGE_REQUEST_STAT;
+      break;
+    }
+
+    case DeviceStorageParams::TDeviceStorageEnumerationParams:
+    {
+      DeviceStorageEnumerationParams p = mParams;
+      type = p.type();
+      requestType = DEVICE_STORAGE_REQUEST_READ;
+      break;
+    }
+
+    default:
+    {
+      return false;
+    }
+  }
+
+  // The 'apps' type is special.  We only want this exposed
+  // if the caller has the "webapps-manage" permission.
+  if (type.EqualsLiteral("apps")) {
+    if (!AssertAppProcessPermission(aParent, "webapps-manage")) {
+      return false;
+    }
+  }
+
+  nsAutoCString permissionName;
+  nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(type, permissionName);
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  nsCString access;
+  rv = DeviceStorageTypeChecker::GetAccessForRequest(requestType, access);
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  permissionName.AppendLiteral("-");
+  permissionName.Append(access);
+
+  if (!AssertAppProcessPermission(aParent, permissionName.get())) {
+    return false;
+  }
+
+  return true;
+}
+
 DeviceStorageRequestParent::~DeviceStorageRequestParent()
 {
   MOZ_COUNT_DTOR(DeviceStorageRequestParent);
 }
 
 NS_IMPL_THREADSAFE_ADDREF(DeviceStorageRequestParent);
 NS_IMPL_THREADSAFE_RELEASE(DeviceStorageRequestParent);
 
--- a/dom/devicestorage/DeviceStorageRequestParent.h
+++ b/dom/devicestorage/DeviceStorageRequestParent.h
@@ -3,39 +3,45 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_devicestorage_DeviceStorageRequestParent_h
 #define mozilla_dom_devicestorage_DeviceStorageRequestParent_h
 
 #include "mozilla/dom/devicestorage/PDeviceStorageRequestParent.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentParent.h"
 
 #include "nsThreadUtils.h"
 #include "nsDeviceStorage.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 namespace devicestorage {
 
 class DeviceStorageRequestParent : public PDeviceStorageRequestParent
 {
 public:
   DeviceStorageRequestParent(const DeviceStorageParams& aParams);
 
   NS_IMETHOD_(nsrefcnt) AddRef();
   NS_IMETHOD_(nsrefcnt) Release();
+
+  bool EnsureRequiredPermissions(mozilla::dom::ContentParent* aParent);
+  void Dispatch();
+
   virtual void ActorDestroy(ActorDestroyReason);
 
 protected:
   ~DeviceStorageRequestParent();
 
 private:
   nsAutoRefCnt mRefCnt;
+  DeviceStorageParams mParams;
 
   class CancelableRunnable : public nsRunnable
   {
   public:
     CancelableRunnable(DeviceStorageRequestParent* aParent)
       : mParent(aParent)
     {
       mCanceled = !(mParent->AddRunnable(this));
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1193,19 +1193,22 @@ ContentParent::DeallocPBrowser(PBrowserP
     TabParent* parent = static_cast<TabParent*>(frame);
     NS_RELEASE(parent);
     return true;
 }
 
 PDeviceStorageRequestParent*
 ContentParent::AllocPDeviceStorageRequest(const DeviceStorageParams& aParams)
 {
-  DeviceStorageRequestParent* result = new DeviceStorageRequestParent(aParams);
-  NS_ADDREF(result);
-  return result;
+  nsRefPtr<DeviceStorageRequestParent> result = new DeviceStorageRequestParent(aParams);
+  if (!result->EnsureRequiredPermissions(this)) {
+      return nullptr;
+  }
+  result->Dispatch();
+  return result.forget().get();
 }
 
 bool
 ContentParent::DeallocPDeviceStorageRequest(PDeviceStorageRequestParent* doomed)
 {
   DeviceStorageRequestParent *parent = static_cast<DeviceStorageRequestParent*>(doomed);
   NS_RELEASE(parent);
   return true;