Bug 786688 - Part 1: Add chrome only openForPrincipal() and deleteForPrincipal(). r=bent
authorJonas Sicking <jonas@sicking.cc>
Tue, 30 Oct 2012 07:07:09 +0100
changeset 111873 a0ac5962820230b62c72572c9defbae3827026ff
parent 111872 cdaa193babf2ad51f27a026dc8e8137ed5904e25
child 111874 90e2bd5252aacdcad158528d75909a6fc6170c59
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersbent
bugs786688
milestone19.0a1
Bug 786688 - Part 1: Add chrome only openForPrincipal() and deleteForPrincipal(). r=bent
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/indexedDB/IDBFactory.cpp
dom/indexedDB/IDBFactory.h
dom/indexedDB/ipc/IndexedDBParent.cpp
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -698,16 +698,34 @@ DOMCI_DATA_NO_CLASS(DOMConstructor)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _class, _helper, _flags)
 
 #define NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(_class, _helper, _flags)          \
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA_WITH_NAME(_class, _class, _helper, \
                                                  _flags)
 
 namespace {
 
+class IDBFactorySH : public nsDOMGenericSH
+{
+protected:
+  IDBFactorySH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
+  { }
+
+  virtual ~IDBFactorySH()
+  { }
+
+public:
+  NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto);
+
+  static nsIClassInfo *doCreate(nsDOMClassInfoData *aData)
+  {
+    return new IDBFactorySH(aData);
+  }
+};
+
 class IDBEventTargetSH : public nsEventTargetSH
 {
 protected:
   IDBEventTargetSH(nsDOMClassInfoData* aData) : nsEventTargetSH(aData)
   { }
 
   virtual ~IDBEventTargetSH()
   { }
@@ -1576,17 +1594,17 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DesktopNotification, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(DesktopNotificationCenter, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(IDBFactory, nsDOMGenericSH,
+  NS_DEFINE_CLASSINFO_DATA(IDBFactory, IDBFactorySH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(IDBFileHandle, FileHandle, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBRequest, IDBEventTargetSH,
                            IDBEVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBDatabase, IDBEventTargetSH,
                            IDBEVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBObjectStore, nsDOMGenericSH,
@@ -7963,16 +7981,98 @@ nsDOMMutationObserverSH::AddProperty(nsI
 void
 nsDOMMutationObserverSH::PreserveWrapper(nsISupports* aNative)
 {
   nsDOMMutationObserver* mutationObserver =
     nsDOMMutationObserver::FromSupports(aNative);
   nsContentUtils::PreserveWrapper(aNative, mutationObserver);
 }
 
+// IDBFactory helper
+
+/* static */
+template<nsresult (*func)(JSContext *cx, unsigned argc, jsval *vp, bool aDelete), bool aDelete>
+JSBool
+IDBFNativeShim(JSContext *cx, unsigned argc, jsval *vp)
+{
+  nsresult rv = (*func)(cx, argc, vp, aDelete);
+  if (NS_FAILED(rv)) {
+    xpc::Throw(cx, rv);
+    return false;
+  }
+
+  return true;  
+}
+
+/* static */ nsresult
+IDBFOpenForPrincipal(JSContext *cx, unsigned argc, JS::Value *vp, bool aDelete)
+{
+  // Just to be on the extra-safe side
+  if (!nsContentUtils::IsCallerChrome()) {
+    MOZ_NOT_REACHED("Shouldn't be possible to get here");
+    return NS_ERROR_FAILURE;
+  }
+
+  JSObject* principalJS;
+  JSString* nameJS;
+  uint32_t version = 0;
+  if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "oS/u",
+                           &principalJS, &nameJS, &version)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (version < 1 && argc >= 3) {
+    return NS_ERROR_TYPE_ERR;
+  }
+
+  nsDependentJSString name;
+  NS_ENSURE_TRUE(name.init(cx, nameJS), NS_ERROR_UNEXPECTED);
+
+  nsCOMPtr<nsIPrincipal> principal = do_QueryWrapper(cx, principalJS);
+  NS_ENSURE_TRUE(principal, NS_ERROR_NO_INTERFACE);
+
+  nsCString extendedOrigin;
+  nsresult rv = principal->GetExtendedOrigin(extendedOrigin);
+  NS_ENSURE_FALSE(extendedOrigin.IsEmpty(), NS_ERROR_UNEXPECTED);
+
+  nsCOMPtr<nsIIDBFactory> factory =
+    do_QueryWrapper(cx, JS_THIS_OBJECT(cx, vp));
+  NS_ENSURE_TRUE(factory, NS_ERROR_NO_INTERFACE);
+
+  nsRefPtr<indexedDB::IDBOpenDBRequest> request;
+  rv = static_cast<indexedDB::IDBFactory*>(factory.get())->
+    OpenCommon(name, version, extendedOrigin, aDelete, cx,
+               getter_AddRefs(request));
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  return WrapNative(cx, JS_GetGlobalForScopeChain(cx),
+                    static_cast<nsIIDBOpenDBRequest*>(request),
+                    &NS_GET_IID(nsIIDBOpenDBRequest), true, vp);
+}
+
+NS_IMETHODIMP
+IDBFactorySH::PostCreatePrototype(JSContext * cx, JSObject * proto)
+{
+  // set up our proto first
+  nsresult rv = nsDOMGenericSH::PostCreatePrototype(cx, proto);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (xpc::AccessCheck::isChrome(js::GetObjectCompartment(proto)) &&
+      (!JS_DefineFunction(cx, proto, "openForPrincipal",
+                          IDBFNativeShim<IDBFOpenForPrincipal, false>,
+                          3, JSPROP_ENUMERATE) ||
+       !JS_DefineFunction(cx, proto, "deleteForPrincipal",
+                          IDBFNativeShim<IDBFOpenForPrincipal, true>,
+                          3, JSPROP_ENUMERATE))) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  return rv;
+}
+
 // IDBEventTarget helper
 
 NS_IMETHODIMP
 IDBEventTargetSH::PreCreate(nsISupports *aNativeObj, JSContext *aCx,
                             JSObject *aGlobalObj, JSObject **aParentObj)
 {
   IDBWrapperCache *target = IDBWrapperCache::FromSupports(aNativeObj);
   JSObject *parent = target->GetParentObject();
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -268,24 +268,27 @@ public:
   static jsid sOnload_id;
   static jsid sOnerror_id;
 
 protected:
   static JSPropertyOp sXPCNativeWrapperGetPropertyOp;
   static JSPropertyOp sXrayWrapperPropertyHolderGetPropertyOp;
 };
 
-
+// THIS ONE ISN'T SAFE!! It assumes that the private of the JSObject is
+// an nsISupports.
 inline
 const nsQueryInterface
 do_QueryWrappedNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj)
 {
   return nsQueryInterface(nsDOMClassInfo::GetNative(wrapper, obj));
 }
 
+// THIS ONE ISN'T SAFE!! It assumes that the private of the JSObject is
+// an nsISupports.
 inline
 const nsQueryInterfaceWithError
 do_QueryWrappedNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj,
                       nsresult *aError)
 
 {
   return nsQueryInterfaceWithError(nsDOMClassInfo::GetNative(wrapper, obj),
                                    aError);
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -494,16 +494,17 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDB
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOwningObject)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 DOMCI_DATA(IDBFactory, IDBFactory)
 
 nsresult
 IDBFactory::OpenCommon(const nsAString& aName,
                        int64_t aVersion,
+                       const nsACString& aASCIIOrigin,
                        bool aDeleting,
                        JSContext* aCallingCx,
                        IDBOpenDBRequest** _retval)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mWindow || mOwningObject, "Must have one of these!");
 
   nsCOMPtr<nsPIDOMWindow> window;
@@ -524,36 +525,36 @@ IDBFactory::OpenCommon(const nsAString& 
   nsRefPtr<IDBOpenDBRequest> request =
     IDBOpenDBRequest::Create(this, window, scriptOwner, aCallingCx);
   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   nsresult rv;
 
   if (IndexedDatabaseManager::IsMainProcess()) {
     nsRefPtr<OpenDatabaseHelper> openHelper =
-      new OpenDatabaseHelper(request, aName, mASCIIOrigin, aVersion, aDeleting,
+      new OpenDatabaseHelper(request, aName, aASCIIOrigin, aVersion, aDeleting,
                              mContentParent, privilege);
 
     rv = openHelper->Init();
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     nsRefPtr<CheckPermissionsHelper> permissionHelper =
       new CheckPermissionsHelper(openHelper, window, aDeleting);
 
     IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
     NS_ASSERTION(mgr, "This should never be null!");
 
     rv =
-      mgr->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(mASCIIOrigin),
+      mgr->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(aASCIIOrigin),
                               openHelper->Id(), permissionHelper);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   }
   else if (aDeleting) {
     nsCOMPtr<nsIAtom> databaseId =
-      IndexedDatabaseManager::GetDatabaseId(mASCIIOrigin, aName);
+      IndexedDatabaseManager::GetDatabaseId(aASCIIOrigin, aName);
     NS_ENSURE_TRUE(databaseId, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     IndexedDBDeleteDatabaseRequestChild* actor =
       new IndexedDBDeleteDatabaseRequestChild(this, request, databaseId);
 
     mActorChild->SendPIndexedDBDeleteDatabaseRequestConstructor(
                                                                actor,
                                                                nsString(aName));
@@ -578,31 +579,31 @@ IDBFactory::Open(const nsAString& aName,
                  uint8_t aArgc,
                  nsIIDBOpenDBRequest** _retval)
 {
   if (aVersion < 1 && aArgc) {
     return NS_ERROR_TYPE_ERR;
   }
 
   nsRefPtr<IDBOpenDBRequest> request;
-  nsresult rv = OpenCommon(aName, aVersion, false, aCx,
+  nsresult rv = OpenCommon(aName, aVersion, mASCIIOrigin, false, aCx,
                            getter_AddRefs(request));
   NS_ENSURE_SUCCESS(rv, rv);
 
   request.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBFactory::DeleteDatabase(const nsAString& aName,
                            JSContext* aCx,
                            nsIIDBOpenDBRequest** _retval)
 {
   nsRefPtr<IDBOpenDBRequest> request;
-  nsresult rv = OpenCommon(aName, 0, true, aCx, getter_AddRefs(request));
+  nsresult rv = OpenCommon(aName, 0, mASCIIOrigin, true, aCx, getter_AddRefs(request));
   NS_ENSURE_SUCCESS(rv, rv);
 
   request.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBFactory::Cmp(const jsval& aFirst,
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -87,16 +87,17 @@ public:
   static nsresult
   SetDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
                       uint64_t aVersion,
                       ObjectStoreInfoArray& aObjectStores);
 
   nsresult
   OpenCommon(const nsAString& aName,
              int64_t aVersion,
+             const nsACString& aASCIIOrigin,
              bool aDeleting,
              JSContext* aCallingCx,
              IDBOpenDBRequest** _retval);
 
   void
   SetActor(IndexedDBChild* aActorChild)
   {
     NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
--- a/dom/indexedDB/ipc/IndexedDBParent.cpp
+++ b/dom/indexedDB/ipc/IndexedDBParent.cpp
@@ -84,18 +84,18 @@ IndexedDBParent::ActorDestroy(ActorDestr
 bool
 IndexedDBParent::RecvPIndexedDBDatabaseConstructor(
                                                PIndexedDBDatabaseParent* aActor,
                                                const nsString& aName,
                                                const uint64_t& aVersion)
 {
   nsRefPtr<IDBOpenDBRequest> request;
   nsresult rv =
-    mFactory->OpenCommon(aName, aVersion, false, nullptr,
-                         getter_AddRefs(request));
+    mFactory->OpenCommon(aName, aVersion, mFactory->GetASCIIOrigin(), false,
+                         nullptr, getter_AddRefs(request));
   NS_ENSURE_SUCCESS(rv, false);
 
   IndexedDBDatabaseParent* actor =
     static_cast<IndexedDBDatabaseParent*>(aActor);
 
   rv = actor->SetOpenRequest(request);
   NS_ENSURE_SUCCESS(rv, false);
 
@@ -108,17 +108,18 @@ IndexedDBParent::RecvPIndexedDBDeleteDat
                                   const nsString& aName)
 {
   IndexedDBDeleteDatabaseRequestParent* actor =
     static_cast<IndexedDBDeleteDatabaseRequestParent*>(aActor);
 
   nsRefPtr<IDBOpenDBRequest> request;
 
   nsresult rv =
-    mFactory->OpenCommon(aName, 0, true, nullptr, getter_AddRefs(request));
+    mFactory->OpenCommon(aName, 0, mFactory->GetASCIIOrigin(), true, nullptr,
+                         getter_AddRefs(request));
   NS_ENSURE_SUCCESS(rv, false);
 
   rv = actor->SetOpenRequest(request);
   NS_ENSURE_SUCCESS(rv, false);
 
   return true;
 }