Bug 735094: Implement new string values (rather than numeric constants) for IndexedDB. r=bent
authorJonas Sicking <jonas@sicking.cc>
Mon, 12 Mar 2012 21:44:45 -0700
changeset 88817 5a7686f1119b038eddbff7d49a169ef1c78f5391
parent 88816 825a808d224f2c7fc5115ce4686a08e1535a230e
child 88818 4d64d2d31843f0f9b7b2385c6b100eb6a636e18b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbent
bugs735094
milestone13.0a1
Bug 735094: Implement new string values (rather than numeric constants) for IndexedDB. r=bent
dom/base/nsDOMClassInfo.cpp
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBCursor.h
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IDBTransaction.cpp
dom/indexedDB/IDBTransaction.h
dom/indexedDB/TransactionThreadPool.cpp
dom/indexedDB/nsIIDBCursor.idl
dom/indexedDB/nsIIDBDatabase.idl
dom/indexedDB/nsIIDBIndex.idl
dom/indexedDB/nsIIDBObjectStore.idl
dom/indexedDB/nsIIDBRequest.idl
dom/indexedDB/nsIIDBTransaction.idl
dom/indexedDB/test/browser_quotaPrompt.html
dom/indexedDB/test/browser_quotaPromptDatabases.html
dom/indexedDB/test/browser_quotaPromptDelete.html
dom/indexedDB/test/test_create_objectStore.html
dom/indexedDB/test/test_deleteDatabase.html
dom/indexedDB/test/test_deleteDatabase_interactions.html
dom/indexedDB/test/test_readonly_transactions.html
dom/indexedDB/test/unit/test_advance.js
dom/indexedDB/test/unit/test_clear.js
dom/indexedDB/test/unit/test_create_index.js
dom/indexedDB/test/unit/test_create_objectStore.js
dom/indexedDB/test/unit/test_cursor_mutation.js
dom/indexedDB/test/unit/test_cursor_update_updates_indexes.js
dom/indexedDB/test/unit/test_cursors.js
dom/indexedDB/test/unit/test_index_empty_keyPath.js
dom/indexedDB/test/unit/test_index_object_cursors.js
dom/indexedDB/test/unit/test_index_update_delete.js
dom/indexedDB/test/unit/test_indexes.js
dom/indexedDB/test/unit/test_indexes_bad_values.js
dom/indexedDB/test/unit/test_keys.js
dom/indexedDB/test/unit/test_multientry.js
dom/indexedDB/test/unit/test_odd_result_order.js
dom/indexedDB/test/unit/test_optionalArguments.js
dom/indexedDB/test/unit/test_overlapping_transactions.js
dom/indexedDB/test/unit/test_request_readyState.js
dom/indexedDB/test/unit/test_setVersion.js
dom/indexedDB/test/unit/test_setVersion_abort.js
dom/indexedDB/test/unit/test_setVersion_events.js
dom/indexedDB/test/unit/test_transaction_abort.js
dom/indexedDB/test/unit/test_transaction_lifetimes_nested.js
dom/indexedDB/test/unit/test_transaction_ordering.js
dom/indexedDB/test/unit/test_writer_starvation.js
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -5687,16 +5687,148 @@ DefineInterfaceConstants(JSContext *cx, 
                              JSPROP_ENUMERATE)) {
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   return NS_OK;
 }
 
+// This code is temporary until we remove support for the constants defined
+// on IDBCursor/IDBRequest/IDBTransaction
+
+struct IDBConstant
+{
+  const char* interface;
+  const char* name;
+  const char* value;
+  
+  static const char* IDBCursor;
+  static const char* IDBRequest;
+  static const char* IDBTransaction;
+};
+
+const char* IDBConstant::IDBCursor = "IDBCursor";
+const char* IDBConstant::IDBRequest = "IDBRequest";
+const char* IDBConstant::IDBTransaction = "IDBTransaction";
+
+static const IDBConstant sIDBConstants[] = {
+  { IDBConstant::IDBCursor,      "NEXT",              "next" },
+  { IDBConstant::IDBCursor,      "NEXT_NO_DUPLICATE", "nextunique" },
+  { IDBConstant::IDBCursor,      "PREV",              "prev" },
+  { IDBConstant::IDBCursor,      "PREV_NO_DUPLICATE", "prevunique" },
+  { IDBConstant::IDBRequest,     "LOADING",           "pending" },
+  { IDBConstant::IDBRequest,     "DONE",              "done" },
+  { IDBConstant::IDBTransaction, "READ_ONLY",         "readonly" },
+  { IDBConstant::IDBTransaction, "READ_WRITE",        "readwrite" },
+  { IDBConstant::IDBTransaction, "VERSION_CHANGE",    "versionchange" },
+};
+
+static JSBool
+IDBConstantGetter(JSContext *cx, JSObject *obj, jsid id, jsval* vp)
+{
+  MOZ_ASSERT(JSID_IS_INT(id));
+  
+  int8_t index = JSID_TO_INT(id);
+  
+  MOZ_ASSERT((uint8_t)index < mozilla::ArrayLength(sIDBConstants));
+
+  const IDBConstant& c = sIDBConstants[index];
+
+  // Put a warning on the console
+  nsString warnText =
+    NS_LITERAL_STRING("The constant ") +
+    NS_ConvertASCIItoUTF16(c.interface) +
+    NS_LITERAL_STRING(".") +
+    NS_ConvertASCIItoUTF16(c.name) +
+    NS_LITERAL_STRING(" has been deprecated. Use the string value \"") +
+    NS_ConvertASCIItoUTF16(c.value) +
+    NS_LITERAL_STRING("\" instead.");
+
+  PRUint64 windowID = 0;
+  nsIScriptContext* context = GetScriptContextFromJSContext(cx);
+  if (context) {
+    nsCOMPtr<nsPIDOMWindow> window =
+      do_QueryInterface(context->GetGlobalObject());
+    if (window) {
+      window = window->GetCurrentInnerWindow();
+    }
+    NS_WARN_IF_FALSE(window, "Missing a window, got a door?");
+    if (window) {
+      windowID = window->WindowID();
+    }
+  }
+
+  nsCOMPtr<nsIScriptError> errorObject =
+    do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
+  NS_WARN_IF_FALSE(errorObject, "Failed to create error object");
+  if (errorObject) {
+    nsresult rv = errorObject->InitWithWindowID(warnText.get(),
+                                                nsnull, // file name
+                                                nsnull, // source line
+                                                0, 0, // Line/col number
+                                                nsIScriptError::warningFlag,
+                                                "DOM Core", windowID);
+    NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to init error object");
+
+    if (NS_SUCCEEDED(rv)) {
+      nsCOMPtr<nsIConsoleService> consoleServ =
+        do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+      if (consoleServ) {
+        consoleServ->LogMessage(errorObject);
+      }
+    }
+  }
+
+  // Redefine property to remove getter
+  NS_ConvertASCIItoUTF16 valStr(c.value);
+  jsval value;
+  if (!xpc::StringToJsval(cx, valStr, &value)) {
+    return JS_FALSE;
+  }
+  if (!::JS_DefineProperty(cx, obj, c.name, value, nsnull, nsnull,
+                           JSPROP_ENUMERATE)) {
+    return JS_FALSE;
+  }
+
+  // Return value
+  *vp = value;
+  return JS_TRUE;
+}
+
+static nsresult
+DefineIDBInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
+{
+  const char* interface;
+  if (aIID->Equals(NS_GET_IID(nsIIDBCursor))) {
+    interface = IDBConstant::IDBCursor;
+  }
+  else if (aIID->Equals(NS_GET_IID(nsIIDBRequest))) {
+    interface = IDBConstant::IDBRequest;
+  }
+  else if (aIID->Equals(NS_GET_IID(nsIIDBTransaction))) {
+    interface = IDBConstant::IDBTransaction;
+  }
+
+  for (int8_t i = 0; i < (int8_t)mozilla::ArrayLength(sIDBConstants); ++i) {
+    const IDBConstant& c = sIDBConstants[i];
+    if (c.interface != interface) {
+      continue;
+    }
+
+    if (!::JS_DefinePropertyWithTinyId(cx, obj, c.name, i, JSVAL_VOID,
+                                       IDBConstantGetter, nsnull,
+                                       JSPROP_ENUMERATE)) {
+      return NS_ERROR_UNEXPECTED;
+    }
+  }
+
+  return NS_OK;
+}
+
 class nsDOMConstructor : public nsIDOMDOMConstructor
 {
 protected:
   nsDOMConstructor(const PRUnichar* aName,
                    bool aIsConstructable,
                    nsPIDOMWindow* aOwner)
     : mClassName(aName),
       mConstructable(aIsConstructable),
@@ -6093,16 +6225,25 @@ nsDOMConstructor::ResolveInterfaceConsta
   }
 
   // Special case for |IDBKeyRange| which gets funny "static" functions.
   if (class_iid->Equals(NS_GET_IID(nsIIDBKeyRange)) &&
       !indexedDB::IDBKeyRange::DefineConstructors(cx, obj)) {
     return NS_ERROR_FAILURE;
   }
 
+  // Special case a few IDB interfaces which for now are getting transitional
+  // constants.
+  if (class_iid->Equals(NS_GET_IID(nsIIDBCursor)) ||
+      class_iid->Equals(NS_GET_IID(nsIIDBRequest)) ||
+      class_iid->Equals(NS_GET_IID(nsIIDBTransaction))) {
+    rv = DefineIDBInterfaceConstants(cx, obj, class_iid);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMConstructor::ToString(nsAString &aResult)
 {
   aResult.AssignLiteral("[object ");
   aResult.Append(mClassName);
@@ -6236,16 +6377,25 @@ ResolvePrototype(nsIXPConnect *aXPConnec
     }
 
     // Special case for |IDBKeyRange| which gets funny "static" functions.
     if (primary_iid->Equals(NS_GET_IID(nsIIDBKeyRange)) &&
         !indexedDB::IDBKeyRange::DefineConstructors(cx, class_obj)) {
       return NS_ERROR_FAILURE;
     }
 
+    // Special case a few IDB interfaces which for now are getting transitional
+    // constants.
+    if (primary_iid->Equals(NS_GET_IID(nsIIDBCursor)) ||
+        primary_iid->Equals(NS_GET_IID(nsIIDBRequest)) ||
+        primary_iid->Equals(NS_GET_IID(nsIIDBTransaction))) {
+      rv = DefineIDBInterfaceConstants(cx, class_obj, primary_iid);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+
     nsCOMPtr<nsIInterfaceInfoManager>
       iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
     NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
 
     iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info));
     NS_ENSURE_TRUE(if_info, NS_ERROR_UNEXPECTED);
 
     const nsIID *iid = nsnull;
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -152,17 +152,17 @@ private:
 
 END_INDEXEDDB_NAMESPACE
 
 // static
 already_AddRefed<IDBCursor>
 IDBCursor::Create(IDBRequest* aRequest,
                   IDBTransaction* aTransaction,
                   IDBObjectStore* aObjectStore,
-                  PRUint16 aDirection,
+                  Direction aDirection,
                   const Key& aRangeKey,
                   const nsACString& aContinueQuery,
                   const nsACString& aContinueToQuery,
                   const Key& aKey,
                   StructuredCloneReadInfo& aCloneReadInfo)
 {
   NS_ASSERTION(aObjectStore, "Null pointer!");
   NS_ASSERTION(!aKey.IsUnset(), "Bad key!");
@@ -180,17 +180,17 @@ IDBCursor::Create(IDBRequest* aRequest,
   return cursor.forget();
 }
 
 // static
 already_AddRefed<IDBCursor>
 IDBCursor::Create(IDBRequest* aRequest,
                   IDBTransaction* aTransaction,
                   IDBIndex* aIndex,
-                  PRUint16 aDirection,
+                  Direction aDirection,
                   const Key& aRangeKey,
                   const nsACString& aContinueQuery,
                   const nsACString& aContinueToQuery,
                   const Key& aKey,
                   const Key& aObjectKey)
 {
   NS_ASSERTION(aIndex, "Null pointer!");
   NS_ASSERTION(!aKey.IsUnset(), "Bad key!");
@@ -210,17 +210,17 @@ IDBCursor::Create(IDBRequest* aRequest,
   return cursor.forget();
 }
 
 // static
 already_AddRefed<IDBCursor>
 IDBCursor::Create(IDBRequest* aRequest,
                   IDBTransaction* aTransaction,
                   IDBIndex* aIndex,
-                  PRUint16 aDirection,
+                  Direction aDirection,
                   const Key& aRangeKey,
                   const nsACString& aContinueQuery,
                   const nsACString& aContinueToQuery,
                   const Key& aKey,
                   const Key& aObjectKey,
                   StructuredCloneReadInfo& aCloneReadInfo)
 {
   NS_ASSERTION(aIndex, "Null pointer!");
@@ -238,21 +238,44 @@ IDBCursor::Create(IDBRequest* aRequest,
   cursor->mKey = aKey;
   cursor->mObjectKey = aObjectKey;
   cursor->mCloneReadInfo.Swap(aCloneReadInfo);
 
   return cursor.forget();
 }
 
 // static
+nsresult
+IDBCursor::ParseDirection(const nsAString& aDirection, Direction* aResult)
+{
+  if (aDirection.EqualsLiteral("next")) {
+    *aResult = NEXT;
+  }
+  else if (aDirection.EqualsLiteral("nextunique")) {
+    *aResult = NEXT_UNIQUE;
+  }
+  else if (aDirection.EqualsLiteral("prev")) {
+    *aResult = PREV;
+  }
+  else if (aDirection.EqualsLiteral("prevunique")) {
+    *aResult = PREV_UNIQUE;
+  }
+  else {
+    return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
+  }
+  
+  return NS_OK;
+}
+
+// static
 already_AddRefed<IDBCursor>
 IDBCursor::CreateCommon(IDBRequest* aRequest,
                         IDBTransaction* aTransaction,
                         IDBObjectStore* aObjectStore,
-                        PRUint16 aDirection,
+                        Direction aDirection,
                         const Key& aRangeKey,
                         const nsACString& aContinueQuery,
                         const nsACString& aContinueToQuery)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aRequest, "Null pointer!");
   NS_ASSERTION(aTransaction, "Null pointer!");
   NS_ASSERTION(aObjectStore, "Null pointer!");
@@ -281,17 +304,17 @@ IDBCursor::CreateCommon(IDBRequest* aReq
   cursor->mRangeKey = aRangeKey;
 
   return cursor.forget();
 }
 
 IDBCursor::IDBCursor()
 : mScriptOwner(nsnull),
   mType(OBJECTSTORE),
-  mDirection(nsIIDBCursor::NEXT),
+  mDirection(IDBCursor::NEXT),
   mCachedKey(JSVAL_VOID),
   mCachedPrimaryKey(JSVAL_VOID),
   mCachedValue(JSVAL_VOID),
   mHaveCachedKey(false),
   mHaveCachedPrimaryKey(false),
   mHaveCachedValue(false),
   mRooted(false),
   mContinueCalled(false),
@@ -324,21 +347,21 @@ IDBCursor::ContinueInternal(const Key& a
   if (!mHaveValue || mContinueCalled) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   mContinueToKey = aKey;
 
 #ifdef DEBUG
   {
-    PRUint16 readyState;
-    if (NS_FAILED(mRequest->GetReadyState(&readyState))) {
+    nsAutoString readyState;
+    if (NS_FAILED(mRequest->GetReadyState(readyState))) {
       NS_ERROR("This should never fail!");
     }
-    NS_ASSERTION(readyState == nsIIDBRequest::DONE, "Should be DONE!");
+    NS_ASSERTION(readyState.EqualsLiteral("done"), "Should be DONE!");
   }
 #endif
 
   mRequest->Reset();
 
   nsRefPtr<ContinueHelper> helper;
   switch (mType) {
     case OBJECTSTORE:
@@ -431,21 +454,34 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBCursor)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBCursor)
 
 DOMCI_DATA(IDBCursor, IDBCursor)
 DOMCI_DATA(IDBCursorWithValue, IDBCursor)
 
 NS_IMETHODIMP
-IDBCursor::GetDirection(PRUint16* aDirection)
+IDBCursor::GetDirection(nsAString& aDirection)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  *aDirection = mDirection;
+  switch(mDirection) {
+    case NEXT:
+      aDirection.AssignLiteral("next");
+      break;
+    case NEXT_UNIQUE:
+      aDirection.AssignLiteral("nextunique");
+      break;
+    case PREV:
+      aDirection.AssignLiteral("prev");
+      break;
+    case PREV_UNIQUE:
+      aDirection.AssignLiteral("prevunique");
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBCursor::GetSource(nsISupports** aSource)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
@@ -557,25 +593,25 @@ IDBCursor::Continue(const jsval &aKey,
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   Key key;
   nsresult rv = key.SetFromJSVal(aCx, aKey);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!key.IsUnset()) {
     switch (mDirection) {
-      case nsIIDBCursor::NEXT:
-      case nsIIDBCursor::NEXT_NO_DUPLICATE:
+      case IDBCursor::NEXT:
+      case IDBCursor::NEXT_UNIQUE:
         if (key <= mKey) {
           return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
         }
         break;
 
-      case nsIIDBCursor::PREV:
-      case nsIIDBCursor::PREV_NO_DUPLICATE:
+      case IDBCursor::PREV:
+      case IDBCursor::PREV_UNIQUE:
         if (key >= mKey) {
           return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
         }
         break;
 
       default:
         NS_NOTREACHED("Unknown direction type!");
     }
@@ -848,18 +884,18 @@ ContinueIndexHelper::BindArgumentsToStat
   if (!mCursor->mRangeKey.IsUnset()) {
     NS_NAMED_LITERAL_CSTRING(rangeKeyName, "range_key");
     rv = mCursor->mRangeKey.BindToStatement(aStatement, rangeKeyName);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Bind object key if duplicates are allowed and we're not continuing to a
   // specific key.
-  if ((mCursor->mDirection == nsIIDBCursor::NEXT ||
-       mCursor->mDirection == nsIIDBCursor::PREV) &&
+  if ((mCursor->mDirection == IDBCursor::NEXT ||
+       mCursor->mDirection == IDBCursor::PREV) &&
        mCursor->mContinueToKey.IsUnset()) {
     NS_ASSERTION(!mCursor->mObjectKey.IsUnset(), "Bad key!");
 
     NS_NAMED_LITERAL_CSTRING(objectKeyName, "object_key");
     rv = mCursor->mObjectKey.BindToStatement(aStatement, objectKeyName);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -72,95 +72,106 @@ class IDBCursor : public nsIIDBCursorWit
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIIDBCURSOR
   NS_DECL_NSIIDBCURSORWITHVALUE
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
 
+  enum Type
+  {
+    OBJECTSTORE = 0,
+    INDEXKEY,
+    INDEXOBJECT
+  };
+
+  enum Direction
+  {
+    NEXT = 0,
+    NEXT_UNIQUE,
+    PREV,
+    PREV_UNIQUE
+  };
+
   // For OBJECTSTORE cursors.
   static
   already_AddRefed<IDBCursor>
   Create(IDBRequest* aRequest,
          IDBTransaction* aTransaction,
          IDBObjectStore* aObjectStore,
-         PRUint16 aDirection,
+         Direction aDirection,
          const Key& aRangeKey,
          const nsACString& aContinueQuery,
          const nsACString& aContinueToQuery,
          const Key& aKey,
          StructuredCloneReadInfo& aCloneReadInfo);
 
   // For INDEXKEY cursors.
   static
   already_AddRefed<IDBCursor>
   Create(IDBRequest* aRequest,
          IDBTransaction* aTransaction,
          IDBIndex* aIndex,
-         PRUint16 aDirection,
+         Direction aDirection,
          const Key& aRangeKey,
          const nsACString& aContinueQuery,
          const nsACString& aContinueToQuery,
          const Key& aKey,
          const Key& aObjectKey);
 
   // For INDEXOBJECT cursors.
   static
   already_AddRefed<IDBCursor>
   Create(IDBRequest* aRequest,
          IDBTransaction* aTransaction,
          IDBIndex* aIndex,
-         PRUint16 aDirection,
+         Direction aDirection,
          const Key& aRangeKey,
          const nsACString& aContinueQuery,
          const nsACString& aContinueToQuery,
          const Key& aKey,
          const Key& aObjectKey,
          StructuredCloneReadInfo& aCloneReadInfo);
 
-  enum Type
-  {
-    OBJECTSTORE = 0,
-    INDEXKEY,
-    INDEXOBJECT
-  };
-
   IDBTransaction* Transaction()
   {
     return mTransaction;
   }
 
+  static nsresult ParseDirection(const nsAString& aDirection,
+                                 Direction* aResult);
+
 protected:
   IDBCursor();
   ~IDBCursor();
 
   static
   already_AddRefed<IDBCursor>
   CreateCommon(IDBRequest* aRequest,
                IDBTransaction* aTransaction,
                IDBObjectStore* aObjectStore,
-               PRUint16 aDirection,
+               Direction aDirection,
                const Key& aRangeKey,
                const nsACString& aContinueQuery,
                const nsACString& aContinueToQuery);
 
   nsresult
   ContinueInternal(const Key& aKey,
                    PRInt32 aCount);
 
   nsRefPtr<IDBRequest> mRequest;
   nsRefPtr<IDBTransaction> mTransaction;
   nsRefPtr<IDBObjectStore> mObjectStore;
   nsRefPtr<IDBIndex> mIndex;
 
   JSObject* mScriptOwner;
 
   Type mType;
-  PRUint16 mDirection;
+  Direction mDirection;
   nsCString mContinueQuery;
   nsCString mContinueToQuery;
 
   // These are cycle-collected!
   jsval mCachedKey;
   jsval mCachedPrimaryKey;
   jsval mCachedValue;
 
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -381,17 +381,17 @@ IDBDatabase::CreateObjectStore(const nsA
                                JSContext* aCx,
                                nsIIDBObjectStore** _retval)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = AsyncConnectionHelper::GetCurrentTransaction();
 
   if (!transaction ||
-      transaction->Mode() != nsIIDBTransaction::VERSION_CHANGE) {
+      transaction->GetMode() != IDBTransaction::VERSION_CHANGE) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   DatabaseInfo* databaseInfo = transaction->DBInfo();
 
   mozilla::dom::IDBObjectStoreParameters params;
   nsString keyPath;
   keyPath.SetIsVoid(true);
@@ -501,17 +501,17 @@ IDBDatabase::CreateObjectStore(const nsA
 NS_IMETHODIMP
 IDBDatabase::DeleteObjectStore(const nsAString& aName)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = AsyncConnectionHelper::GetCurrentTransaction();
 
   if (!transaction ||
-      transaction->Mode() != nsIIDBTransaction::VERSION_CHANGE) {
+      transaction->GetMode() != IDBTransaction::VERSION_CHANGE) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   DatabaseInfo* info = transaction->DBInfo();
   ObjectStoreInfo* objectStoreInfo = info->GetObjectStore(aName);
   if (!objectStoreInfo) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
   }
@@ -523,17 +523,17 @@ IDBDatabase::DeleteObjectStore(const nsA
 
   transaction->RemoveObjectStore(aName);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBDatabase::Transaction(const jsval& aStoreNames,
-                         PRUint16 aMode,
+                         const nsAString& aMode,
                          JSContext* aCx,
                          PRUint8 aOptionalArgCount,
                          nsIIDBTransaction** _retval)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (IndexedDatabaseManager::IsShuttingDown()) {
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -542,25 +542,25 @@ IDBDatabase::Transaction(const jsval& aS
   if (mClosed) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   if (mRunningVersionChange) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
+  IDBTransaction::Mode transactionMode = IDBTransaction::READ_ONLY;
   if (aOptionalArgCount) {
-    if (aMode != nsIIDBTransaction::READ_WRITE &&
-        aMode != nsIIDBTransaction::READ_ONLY) {
+    if (aMode.EqualsLiteral("readwrite")) {
+      transactionMode = IDBTransaction::READ_WRITE;
+    }
+    else if (!aMode.EqualsLiteral("readonly")) {
       return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
     }
   }
-  else {
-    aMode = nsIIDBTransaction::READ_ONLY;
-  }
 
   nsresult rv;
   nsTArray<nsString> storesToOpen;
 
   if (!JSVAL_IS_PRIMITIVE(aStoreNames)) {
     JSObject* obj = JSVAL_TO_OBJECT(aStoreNames);
 
     // See if this is a JS array.
@@ -652,17 +652,17 @@ IDBDatabase::Transaction(const jsval& aS
   DatabaseInfo* info = Info();
   for (PRUint32 index = 0; index < storesToOpen.Length(); index++) {
     if (!info->ContainsStoreName(storesToOpen[index])) {
       return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
     }
   }
 
   nsRefPtr<IDBTransaction> transaction =
-    IDBTransaction::Create(this, storesToOpen, aMode, false);
+    IDBTransaction::Create(this, storesToOpen, transactionMode, false);
   NS_ENSURE_TRUE(transaction, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   transaction.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBDatabase::Close()
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -181,17 +181,17 @@ protected:
 
 class OpenKeyCursorHelper : public AsyncConnectionHelper
 {
 public:
   OpenKeyCursorHelper(IDBTransaction* aTransaction,
                       IDBRequest* aRequest,
                       IDBIndex* aIndex,
                       IDBKeyRange* aKeyRange,
-                      PRUint16 aDirection)
+                      IDBCursor::Direction aDirection)
   : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
     mKeyRange(aKeyRange), mDirection(aDirection)
   { }
 
   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
   nsresult GetSuccessResult(JSContext* aCx,
                             jsval* aVal);
 
@@ -201,34 +201,34 @@ public:
     mKeyRange = nsnull;
     AsyncConnectionHelper::ReleaseMainThreadObjects();
   }
 
 private:
   // In-params.
   nsRefPtr<IDBIndex> mIndex;
   nsRefPtr<IDBKeyRange> mKeyRange;
-  const PRUint16 mDirection;
+  const IDBCursor::Direction mDirection;
 
   // Out-params.
   Key mKey;
   Key mObjectKey;
   nsCString mContinueQuery;
   nsCString mContinueToQuery;
   Key mRangeKey;
 };
 
 class OpenCursorHelper : public AsyncConnectionHelper
 {
 public:
   OpenCursorHelper(IDBTransaction* aTransaction,
                    IDBRequest* aRequest,
                    IDBIndex* aIndex,
                    IDBKeyRange* aKeyRange,
-                   PRUint16 aDirection)
+                   IDBCursor::Direction aDirection)
   : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
     mKeyRange(aKeyRange), mDirection(aDirection)
   { }
 
   ~OpenCursorHelper()
   {
     IDBObjectStore::ClearStructuredCloneBuffer(mCloneReadInfo.mCloneBuffer);
   }
@@ -243,17 +243,17 @@ public:
     mKeyRange = nsnull;
     AsyncConnectionHelper::ReleaseMainThreadObjects();
   }
 
 private:
   // In-params.
   nsRefPtr<IDBIndex> mIndex;
   nsRefPtr<IDBKeyRange> mKeyRange;
-  const PRUint16 mDirection;
+  const IDBCursor::Direction mDirection;
 
   // Out-params.
   Key mKey;
   Key mObjectKey;
   StructuredCloneReadInfo mCloneReadInfo;
   nsCString mContinueQuery;
   nsCString mContinueToQuery;
   Key mRangeKey;
@@ -577,100 +577,90 @@ IDBIndex::GetAllKeys(const jsval& aKey,
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   request.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBIndex::OpenCursor(const jsval& aKey,
-                     PRUint16 aDirection,
+                     const nsAString& aDirection,
                      JSContext* aCx,
                      PRUint8 aOptionalArgCount,
                      nsIIDBRequest** _retval)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
   }
 
   nsresult rv;
 
+  IDBCursor::Direction direction = IDBCursor::NEXT;
+
   nsRefPtr<IDBKeyRange> keyRange;
   if (aOptionalArgCount) {
     rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aOptionalArgCount >= 2) {
-      if (aDirection != nsIIDBCursor::NEXT &&
-          aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE &&
-          aDirection != nsIIDBCursor::PREV &&
-          aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) {
-        return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
-      }
-    }
-    else {
-      aDirection = nsIIDBCursor::NEXT;
+      rv = IDBCursor::ParseDirection(aDirection, &direction);
+      NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   nsRefPtr<OpenCursorHelper> helper =
-    new OpenCursorHelper(transaction, request, this, keyRange, aDirection);
+    new OpenCursorHelper(transaction, request, this, keyRange, direction);
 
   rv = helper->DispatchToTransactionPool();
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   request.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBIndex::OpenKeyCursor(const jsval& aKey,
-                        PRUint16 aDirection,
+                        const nsAString& aDirection,
                         JSContext* aCx,
                         PRUint8 aOptionalArgCount,
                         nsIIDBRequest** _retval)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
   }
 
   nsresult rv;
 
+  IDBCursor::Direction direction = IDBCursor::NEXT;
+
   nsRefPtr<IDBKeyRange> keyRange;
   if (aOptionalArgCount) {
     rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aOptionalArgCount >= 2) {
-      if (aDirection != nsIIDBCursor::NEXT &&
-          aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE &&
-          aDirection != nsIIDBCursor::PREV &&
-          aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) {
-        return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
-      }
-    }
-    else {
-      aDirection = nsIIDBCursor::NEXT;
+      rv = IDBCursor::ParseDirection(aDirection, &direction);
+      NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   nsRefPtr<OpenKeyCursorHelper> helper =
-    new OpenKeyCursorHelper(transaction, request, this, keyRange, aDirection);
+    new OpenKeyCursorHelper(transaction, request, this, keyRange, direction);
 
   rv = helper->DispatchToTransactionPool();
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   request.forget(_retval);
   return NS_OK;
 }
 
@@ -1027,26 +1017,26 @@ OpenKeyCursorHelper::DoDatabaseWork(mozI
 
   nsCString keyRangeClause;
   if (mKeyRange) {
     mKeyRange->GetBindingClause(value, keyRangeClause);
   }
 
   nsCAutoString directionClause(" ORDER BY value ");
   switch (mDirection) {
-    case nsIIDBCursor::NEXT:
-    case nsIIDBCursor::NEXT_NO_DUPLICATE:
+    case IDBCursor::NEXT:
+    case IDBCursor::NEXT_UNIQUE:
       directionClause += NS_LITERAL_CSTRING("ASC, object_data_key ASC");
       break;
 
-    case nsIIDBCursor::PREV:
+    case IDBCursor::PREV:
       directionClause += NS_LITERAL_CSTRING("DESC, object_data_key DESC");
       break;
 
-    case nsIIDBCursor::PREV_NO_DUPLICATE:
+    case IDBCursor::PREV_UNIQUE:
       directionClause += NS_LITERAL_CSTRING("DESC, object_data_key ASC");
       break;
 
     default:
       NS_NOTREACHED("Unknown direction!");
   }
   nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, object_data_key "
                                             "FROM ") + table +
@@ -1087,17 +1077,17 @@ OpenKeyCursorHelper::DoDatabaseWork(mozI
   // Now we need to make the query to get the next match.
   nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT value, object_data_key"
                                                 " FROM ") + table +
                              NS_LITERAL_CSTRING(" WHERE index_id = :id");
 
   NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
 
   switch (mDirection) {
-    case nsIIDBCursor::NEXT:
+    case IDBCursor::NEXT:
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Upper();
       }
       mContinueQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND value >= :current_key AND "
@@ -1107,33 +1097,33 @@ OpenKeyCursorHelper::DoDatabaseWork(mozI
         NS_LITERAL_CSTRING(" LIMIT ");
       mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND value >= :current_key ") +
         directionClause +
         NS_LITERAL_CSTRING(" LIMIT ");
       break;
 
-    case nsIIDBCursor::NEXT_NO_DUPLICATE:
+    case IDBCursor::NEXT_UNIQUE:
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Upper();
       }
       mContinueQuery =
         queryStart + NS_LITERAL_CSTRING(" AND value > :current_key") +
         directionClause +
         NS_LITERAL_CSTRING(" LIMIT ");
       mContinueToQuery =
         queryStart + NS_LITERAL_CSTRING(" AND value >= :current_key") +
         directionClause +
         NS_LITERAL_CSTRING(" LIMIT ");
       break;
 
-    case nsIIDBCursor::PREV:
+    case IDBCursor::PREV:
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Lower();
       }
 
       mContinueQuery =
         queryStart +
@@ -1144,17 +1134,17 @@ OpenKeyCursorHelper::DoDatabaseWork(mozI
         NS_LITERAL_CSTRING(" LIMIT ");
       mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND value <= :current_key ") +
         directionClause +
         NS_LITERAL_CSTRING(" LIMIT ");
       break;
 
-    case nsIIDBCursor::PREV_NO_DUPLICATE:
+    case IDBCursor::PREV_UNIQUE:
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Lower();
       }
       mContinueQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND value < :current_key") +
@@ -1208,28 +1198,28 @@ OpenCursorHelper::DoDatabaseWork(mozISto
 
   nsCString keyRangeClause;
   if (mKeyRange) {
     mKeyRange->GetBindingClause(value, keyRangeClause);
   }
 
   nsCAutoString directionClause(" ORDER BY index_table.value ");
   switch (mDirection) {
-    case nsIIDBCursor::NEXT:
-    case nsIIDBCursor::NEXT_NO_DUPLICATE:
+    case IDBCursor::NEXT:
+    case IDBCursor::NEXT_UNIQUE:
       directionClause +=
         NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
       break;
 
-    case nsIIDBCursor::PREV:
+    case IDBCursor::PREV:
       directionClause +=
         NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
       break;
 
-    case nsIIDBCursor::PREV_NO_DUPLICATE:
+    case IDBCursor::PREV_UNIQUE:
       directionClause +=
         NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
       break;
 
     default:
       NS_NOTREACHED("Unknown direction!");
   }
 
@@ -1287,17 +1277,17 @@ OpenCursorHelper::DoDatabaseWork(mozISto
                        "index_table.object_data_id = object_data.id "
                        "WHERE index_table.index_id = :id");
 
   NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
 
   NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");
 
   switch (mDirection) {
-    case nsIIDBCursor::NEXT:
+    case IDBCursor::NEXT:
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Upper();
       }
       mContinueQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key AND "
@@ -1305,33 +1295,33 @@ OpenCursorHelper::DoDatabaseWork(mozISto
                            "  index_table.object_data_key > :object_key ) ") +
         directionClause + limit;
       mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
         directionClause + limit;
       break;
 
-    case nsIIDBCursor::NEXT_NO_DUPLICATE:
+    case IDBCursor::NEXT_UNIQUE:
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Upper();
       }
       mContinueQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND index_table.value > :current_key") +
         directionClause + limit;
       mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
         directionClause + limit;
       break;
 
-    case nsIIDBCursor::PREV:
+    case IDBCursor::PREV:
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Lower();
       }
       mContinueQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND index_table.value <= :current_key AND "
@@ -1339,17 +1329,17 @@ OpenCursorHelper::DoDatabaseWork(mozISto
                            "  index_table.object_data_key < :object_key ) ") +
         directionClause + limit;
       mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
         directionClause + limit;
       break;
 
-    case nsIIDBCursor::PREV_NO_DUPLICATE:
+    case IDBCursor::PREV_UNIQUE:
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Lower();
       }
       mContinueQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND index_table.value < :current_key") +
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -193,17 +193,17 @@ protected:
 
 class OpenCursorHelper : public AsyncConnectionHelper
 {
 public:
   OpenCursorHelper(IDBTransaction* aTransaction,
                    IDBRequest* aRequest,
                    IDBObjectStore* aObjectStore,
                    IDBKeyRange* aKeyRange,
-                   PRUint16 aDirection)
+                   IDBCursor::Direction aDirection)
   : AsyncConnectionHelper(aTransaction, aRequest), mObjectStore(aObjectStore),
     mKeyRange(aKeyRange), mDirection(aDirection)
   { }
 
   ~OpenCursorHelper()
   {
     IDBObjectStore::ClearStructuredCloneBuffer(mCloneReadInfo.mCloneBuffer);
   }
@@ -219,17 +219,17 @@ public:
     IDBObjectStore::ClearStructuredCloneBuffer(mCloneReadInfo.mCloneBuffer);
     AsyncConnectionHelper::ReleaseMainThreadObjects();
   }
 
 private:
   // In-params.
   nsRefPtr<IDBObjectStore> mObjectStore;
   nsRefPtr<IDBKeyRange> mKeyRange;
-  const PRUint16 mDirection;
+  const IDBCursor::Direction mDirection;
 
   // Out-params.
   Key mKey;
   StructuredCloneReadInfo mCloneReadInfo;
   nsCString mContinueQuery;
   nsCString mContinueToQuery;
   Key mRangeKey;
 };
@@ -1632,52 +1632,47 @@ IDBObjectStore::Clear(nsIIDBRequest** _r
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   request.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBObjectStore::OpenCursor(const jsval& aKey,
-                           PRUint16 aDirection,
+                           const nsAString& aDirection,
                            JSContext* aCx,
                            PRUint8 aOptionalArgCount,
                            nsIIDBRequest** _retval)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
   }
 
   nsresult rv;
 
+  IDBCursor::Direction direction = IDBCursor::NEXT;
+
   nsRefPtr<IDBKeyRange> keyRange;
   if (aOptionalArgCount) {
     rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aOptionalArgCount >= 2) {
-      if (aDirection != nsIIDBCursor::NEXT &&
-          aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE &&
-          aDirection != nsIIDBCursor::PREV &&
-          aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) {
-        return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
-      }
-    }
-    else {
-      aDirection = nsIIDBCursor::NEXT;
+      rv = IDBCursor::ParseDirection(aDirection, &direction);
+      NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   nsRefPtr<OpenCursorHelper> helper =
-    new OpenCursorHelper(mTransaction, request, this, keyRange, aDirection);
+    new OpenCursorHelper(mTransaction, request, this, keyRange, direction);
 
   rv = helper->DispatchToTransactionPool();
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   request.forget(_retval);
   return NS_OK;
 }
 
@@ -1745,17 +1740,17 @@ IDBObjectStore::CreateIndex(const nsAStr
     keyPath = str;
   }
 
   // Check name and current mode
   IDBTransaction* transaction = AsyncConnectionHelper::GetCurrentTransaction();
 
   if (!transaction ||
       transaction != mTransaction ||
-      mTransaction->Mode() != nsIIDBTransaction::VERSION_CHANGE) {
+      mTransaction->GetMode() != IDBTransaction::VERSION_CHANGE) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   bool found = false;
   PRUint32 indexCount = mInfo->indexes.Length();
   for (PRUint32 index = 0; index < indexCount; index++) {
     if (mInfo->indexes[index].name == aName) {
       found = true;
@@ -1871,17 +1866,17 @@ NS_IMETHODIMP
 IDBObjectStore::DeleteIndex(const nsAString& aName)
 {
   NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = AsyncConnectionHelper::GetCurrentTransaction();
 
   if (!transaction ||
       transaction != mTransaction ||
-      mTransaction->Mode() != nsIIDBTransaction::VERSION_CHANGE) {
+      mTransaction->GetMode() != IDBTransaction::VERSION_CHANGE) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   NS_ASSERTION(mTransaction->IsOpen(), "Impossible!");
 
   PRUint32 index = 0;
   for (; index < mInfo->indexes.Length(); index++) {
     if (mInfo->indexes[index].name == aName) {
@@ -2280,23 +2275,23 @@ OpenCursorHelper::DoDatabaseWork(mozISto
 
   nsCString keyRangeClause;
   if (mKeyRange) {
     mKeyRange->GetBindingClause(keyValue, keyRangeClause);
   }
 
   nsCAutoString directionClause;
   switch (mDirection) {
-    case nsIIDBCursor::NEXT:
-    case nsIIDBCursor::NEXT_NO_DUPLICATE:
+    case IDBCursor::NEXT:
+    case IDBCursor::NEXT_UNIQUE:
       directionClause.AssignLiteral(" ORDER BY key_value ASC");
       break;
 
-    case nsIIDBCursor::PREV:
-    case nsIIDBCursor::PREV_NO_DUPLICATE:
+    case IDBCursor::PREV:
+    case IDBCursor::PREV_UNIQUE:
       directionClause.AssignLiteral(" ORDER BY key_value DESC");
       break;
 
     default:
       NS_NOTREACHED("Unknown direction type!");
   }
 
   nsCString firstQuery = NS_LITERAL_CSTRING("SELECT key_value, data, file_ids "
@@ -2339,34 +2334,34 @@ OpenCursorHelper::DoDatabaseWork(mozISto
   // Now we need to make the query to get the next match.
   keyRangeClause.Truncate();
   nsCAutoString continueToKeyRangeClause;
 
   NS_NAMED_LITERAL_CSTRING(currentKey, "current_key");
   NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
 
   switch (mDirection) {
-    case nsIIDBCursor::NEXT:
-    case nsIIDBCursor::NEXT_NO_DUPLICATE:
+    case IDBCursor::NEXT:
+    case IDBCursor::NEXT_UNIQUE:
       AppendConditionClause(keyValue, currentKey, false, false,
                             keyRangeClause);
       AppendConditionClause(keyValue, currentKey, false, true,
                             continueToKeyRangeClause);
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(keyValue, rangeKey, true,
                               !mKeyRange->IsUpperOpen(), keyRangeClause);
         AppendConditionClause(keyValue, rangeKey, true,
                               !mKeyRange->IsUpperOpen(),
                               continueToKeyRangeClause);
         mRangeKey = mKeyRange->Upper();
       }
       break;
 
-    case nsIIDBCursor::PREV:
-    case nsIIDBCursor::PREV_NO_DUPLICATE:
+    case IDBCursor::PREV:
+    case IDBCursor::PREV_UNIQUE:
       AppendConditionClause(keyValue, currentKey, true, false, keyRangeClause);
       AppendConditionClause(keyValue, currentKey, true, true,
                            continueToKeyRangeClause);
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(keyValue, rangeKey, false,
                               !mKeyRange->IsLowerOpen(), keyRangeClause);
         AppendConditionClause(keyValue, rangeKey, false,
                               !mKeyRange->IsLowerOpen(),
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -185,23 +185,26 @@ IDBRequest::RootResultValInternal()
 
 void
 IDBRequest::UnrootResultValInternal()
 {
   NS_DROP_JS_OBJECTS(this, IDBRequest);
 }
 
 NS_IMETHODIMP
-IDBRequest::GetReadyState(PRUint16* aReadyState)
+IDBRequest::GetReadyState(nsAString& aReadyState)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  *aReadyState = mHaveResultOrErrorCode ?
-                 nsIIDBRequest::DONE :
-                 nsIIDBRequest::LOADING;
+  if (mHaveResultOrErrorCode) {
+    aReadyState.AssignLiteral("done");
+  }
+  else {
+    aReadyState.AssignLiteral("pending");
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBRequest::GetSource(nsISupports** aSource)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -105,17 +105,17 @@ NS_IMPL_QUERY_INTERFACE1(StartTransactio
 StartTransactionRunnable gStartTransactionRunnable;
 
 } // anonymous namespace
 
 // static
 already_AddRefed<IDBTransaction>
 IDBTransaction::Create(IDBDatabase* aDatabase,
                        nsTArray<nsString>& aObjectStoreNames,
-                       PRUint16 aMode,
+                       Mode aMode,
                        bool aDispatchDelayed)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsRefPtr<IDBTransaction> transaction = new IDBTransaction();
 
   transaction->BindToOwner(aDatabase);
   if (!transaction->SetScriptOwner(aDatabase->GetScriptOwner())) {
@@ -151,27 +151,27 @@ IDBTransaction::Create(IDBDatabase* aDat
     transaction->mCreatedRecursionDepth = depth - 1;
 
     rv = thread->AddObserver(transaction);
     NS_ENSURE_SUCCESS(rv, nsnull);
 
     transaction->mCreating = true;
   }
 
-  if (aMode != nsIIDBTransaction::VERSION_CHANGE) {
+  if (aMode != IDBTransaction::VERSION_CHANGE) {
     TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
     pool->Dispatch(transaction, &gStartTransactionRunnable, false, nsnull);
   }
 
   return transaction.forget();
 }
 
 IDBTransaction::IDBTransaction()
-: mReadyState(nsIIDBTransaction::INITIAL),
-  mMode(nsIIDBTransaction::READ_ONLY),
+: mReadyState(IDBTransaction::INITIAL),
+  mMode(IDBTransaction::READ_ONLY),
   mPendingRequests(0),
   mCreatedRecursionDepth(0),
   mSavepointCount(0),
   mAborted(false),
   mCreating(false)
 #ifdef DEBUG
   , mFiredCompleteOrAbort(false)
 #endif
@@ -191,41 +191,41 @@ IDBTransaction::~IDBTransaction()
   nsContentUtils::ReleaseWrapper(static_cast<nsIDOMEventTarget*>(this), this);
 }
 
 void
 IDBTransaction::OnNewRequest()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   if (!mPendingRequests) {
-    NS_ASSERTION(mReadyState == nsIIDBTransaction::INITIAL,
+    NS_ASSERTION(mReadyState == IDBTransaction::INITIAL,
                  "Reusing a transaction!");
-    mReadyState = nsIIDBTransaction::LOADING;
+    mReadyState = IDBTransaction::LOADING;
   }
   ++mPendingRequests;
 }
 
 void
 IDBTransaction::OnRequestFinished()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mPendingRequests, "Mismatched calls!");
   --mPendingRequests;
   if (!mPendingRequests) {
-    NS_ASSERTION(mAborted || mReadyState == nsIIDBTransaction::LOADING,
+    NS_ASSERTION(mAborted || mReadyState == IDBTransaction::LOADING,
                  "Bad state!");
     mReadyState = IDBTransaction::COMMITTING;
     CommitOrRollback();
   }
 }
 
 void
 IDBTransaction::RemoveObjectStore(const nsAString& aName)
 {
-  NS_ASSERTION(mMode == nsIIDBTransaction::VERSION_CHANGE,
+  NS_ASSERTION(mMode == IDBTransaction::VERSION_CHANGE,
                "Only remove object stores on VERSION_CHANGE transactions");
 
   mDatabaseInfo->RemoveObjectStore(aName);
 
   for (PRUint32 i = 0; i < mCreatedObjectStores.Length(); i++) {
     if (mCreatedObjectStores[i]->Name() == aName) {
       mCreatedObjectStores.RemoveElementAt(i);
       break;
@@ -338,17 +338,17 @@ IDBTransaction::GetOrCreateConnection(mo
     nsCOMPtr<mozIStorageConnection> connection =
       IDBFactory::GetConnection(mDatabase->FilePath());
     NS_ENSURE_TRUE(connection, NS_ERROR_FAILURE);
 
     nsresult rv;
 
     nsRefPtr<UpdateRefcountFunction> function;
     nsCString beginTransaction;
-    if (mMode != nsIIDBTransaction::READ_ONLY) {
+    if (mMode != IDBTransaction::READ_ONLY) {
       function = new UpdateRefcountFunction(Database()->Manager());
       NS_ENSURE_TRUE(function, NS_ERROR_OUT_OF_MEMORY);
 
       rv = function->Init();
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = connection->CreateFunction(
         NS_LITERAL_CSTRING("update_refcount"), 2, function);
@@ -411,28 +411,28 @@ IDBTransaction::GetCachedStatement(const
 }
 
 bool
 IDBTransaction::IsOpen() const
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   // If we haven't started anything then we're open.
-  if (mReadyState == nsIIDBTransaction::INITIAL) {
+  if (mReadyState == IDBTransaction::INITIAL) {
     NS_ASSERTION(AsyncConnectionHelper::GetCurrentTransaction() != this,
                  "This should be some other transaction (or null)!");
     return true;
   }
 
   // If we've already started then we need to check to see if we still have the
   // mCreating flag set. If we do (i.e. we haven't returned to the event loop
   // from the time we were created) then we are open. Otherwise check the
   // currently running transaction to see if it's the same. We only allow other
   // requests to be made if this transaction is currently running.
-  if (mReadyState == nsIIDBTransaction::LOADING) {
+  if (mReadyState == IDBTransaction::LOADING) {
     if (mCreating) {
       return true;
     }
 
     if (AsyncConnectionHelper::GetCurrentTransaction() == this) {
       return true;
     }
   }
@@ -523,30 +523,31 @@ IDBTransaction::GetDb(nsIIDBDatabase** a
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   NS_ADDREF(*aDB = mDatabase);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-IDBTransaction::GetReadyState(PRUint16* aReadyState)
+IDBTransaction::GetMode(nsAString& aMode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  *aReadyState = mReadyState;
-  return NS_OK;
-}
+  switch(mMode) {
+    case READ_ONLY:
+      aMode.AssignLiteral("readonly");
+      break;
+    case READ_WRITE:
+      aMode.AssignLiteral("readwrite");
+      break;
+    case VERSION_CHANGE:
+      aMode.AssignLiteral("versionchange");
+  }
 
-NS_IMETHODIMP
-IDBTransaction::GetMode(PRUint16* aMode)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  *aMode = mMode;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBTransaction::GetObjectStoreNames(nsIDOMDOMStringList** aObjectStores)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
@@ -581,17 +582,17 @@ IDBTransaction::ObjectStore(const nsAStr
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!IsOpen()) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   ObjectStoreInfo* info = nsnull;
 
-  if (mMode == nsIIDBTransaction::VERSION_CHANGE ||
+  if (mMode == IDBTransaction::VERSION_CHANGE ||
       mObjectStoreNames.Contains(aName)) {
     info = mDatabaseInfo->GetObjectStore(aName);
   }
 
   if (!info) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
   }
 
@@ -609,22 +610,22 @@ IDBTransaction::Abort()
 
   // We can't use IsOpen here since we need it to be possible to call Abort()
   // even from outside of transaction callbacks.
   if (mReadyState != IDBTransaction::INITIAL &&
       mReadyState != IDBTransaction::LOADING) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
-  bool needToCommitOrRollback = mReadyState == nsIIDBTransaction::INITIAL;
+  bool needToCommitOrRollback = mReadyState == IDBTransaction::INITIAL;
 
   mAborted = true;
-  mReadyState = nsIIDBTransaction::DONE;
+  mReadyState = IDBTransaction::DONE;
 
-  if (Mode() == nsIIDBTransaction::VERSION_CHANGE) {
+  if (Mode() == IDBTransaction::VERSION_CHANGE) {
     // If a version change transaction is aborted, the db must be closed
     mDatabase->Close();
   }
 
   // Fire the abort event if there are no outstanding requests. Otherwise the
   // abort event will be fired when all outstanding requests finish.
   if (needToCommitOrRollback) {
     return CommitOrRollback();
@@ -671,18 +672,18 @@ IDBTransaction::AfterProcessNextEvent(ns
                "Should be impossible!");
   NS_ASSERTION(mCreating, "Should be true!");
 
   if (aRecursionDepth == mCreatedRecursionDepth) {
     // We're back at the event loop, no longer newborn.
     mCreating = false;
 
     // Maybe set the readyState to DONE if there were no requests generated.
-    if (mReadyState == nsIIDBTransaction::INITIAL) {
-      mReadyState = nsIIDBTransaction::DONE;
+    if (mReadyState == IDBTransaction::INITIAL) {
+      mReadyState = IDBTransaction::DONE;
 
       if (NS_FAILED(CommitOrRollback())) {
         NS_WARNING("Failed to commit!");
       }
     }
 
     // No longer need to observe thread events.
     if(NS_FAILED(aThread->RemoveObserver(this))) {
@@ -719,29 +720,29 @@ CommitHelper::~CommitHelper()
 NS_IMPL_THREADSAFE_ISUPPORTS1(CommitHelper, nsIRunnable)
 
 NS_IMETHODIMP
 CommitHelper::Run()
 {
   if (NS_IsMainThread()) {
     NS_ASSERTION(mDoomedObjects.IsEmpty(), "Didn't release doomed objects!");
 
-    mTransaction->mReadyState = nsIIDBTransaction::DONE;
+    mTransaction->mReadyState = IDBTransaction::DONE;
 
     // Release file infos on the main thread, so they will eventually get
     // destroyed on correct thread.
     mTransaction->ClearCreatedFileInfos();
     if (mUpdateFileRefcountFunction) {
       mUpdateFileRefcountFunction->ClearFileInfoEntries();
       mUpdateFileRefcountFunction = nsnull;
     }
 
     nsCOMPtr<nsIDOMEvent> event;
     if (mAborted) {
-      if (mTransaction->Mode() == nsIIDBTransaction::VERSION_CHANGE) {
+      if (mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE) {
         // This will make the database take a snapshot of it's DatabaseInfo
         mTransaction->Database()->Close();
         // Then remove the info from the hash as it contains invalid data.
         DatabaseInfo::Remove(mTransaction->Database()->Id());
       }
 
       event = CreateGenericEvent(NS_LITERAL_STRING(ABORT_EVT_STR),
                                  eDoesBubble, eNotCancelable);
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -88,20 +88,35 @@ class IDBTransaction : public IDBWrapper
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIIDBTRANSACTION
   NS_DECL_NSITHREADOBSERVER
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, IDBWrapperCache)
 
+  enum Mode
+  {
+    READ_ONLY = 0,
+    READ_WRITE,
+    VERSION_CHANGE
+  };
+
+  enum ReadyState
+  {
+    INITIAL = 0,
+    LOADING,
+    COMMITTING,
+    DONE
+  };
+
   static already_AddRefed<IDBTransaction>
   Create(IDBDatabase* aDatabase,
          nsTArray<nsString>& aObjectStoreNames,
-         PRUint16 aMode,
+         Mode aMode,
          bool aDispatchDelayed);
 
   // nsIDOMEventTarget
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
   void OnNewRequest();
   void OnRequestFinished();
 
@@ -125,26 +140,26 @@ public:
   {
     return GetCachedStatement(NS_LITERAL_CSTRING(aQuery));
   }
 
   bool IsOpen() const;
 
   bool IsWriteAllowed() const
   {
-    return mMode == nsIIDBTransaction::READ_WRITE ||
-           mMode == nsIIDBTransaction::VERSION_CHANGE;
+    return mMode == READ_WRITE || mMode == VERSION_CHANGE;
   }
 
   bool IsAborted() const
   {
     return mAborted;
   }
 
-  PRUint16 Mode()
+  // 'Get' prefix is to avoid name collisions with the enum
+  Mode GetMode()
   {
     return mMode;
   }
 
   IDBDatabase* Database()
   {
     NS_ASSERTION(mDatabase, "This should never be null!");
     return mDatabase;
@@ -167,18 +182,18 @@ private:
   IDBTransaction();
   ~IDBTransaction();
 
   nsresult CommitOrRollback();
 
   nsRefPtr<IDBDatabase> mDatabase;
   nsRefPtr<DatabaseInfo> mDatabaseInfo;
   nsTArray<nsString> mObjectStoreNames;
-  PRUint16 mReadyState;
-  PRUint16 mMode;
+  ReadyState mReadyState;
+  Mode mMode;
   PRUint32 mPendingRequests;
   PRUint32 mCreatedRecursionDepth;
 
   // Only touched on the main thread.
   NS_DECL_EVENT_HANDLER(error)
   NS_DECL_EVENT_HANDLER(complete)
   NS_DECL_EVENT_HANDLER(abort)
 
--- a/dom/indexedDB/TransactionThreadPool.cpp
+++ b/dom/indexedDB/TransactionThreadPool.cpp
@@ -270,24 +270,24 @@ TransactionThreadPool::FinishTransaction
         count--;
 
         continue;
       }
 
       const nsTArray<nsString>& objectStores = transaction->mObjectStoreNames;
 
       bool dummy;
-      if (transaction->mMode == nsIIDBTransaction::READ_WRITE) {
+      if (transaction->mMode == IDBTransaction::READ_WRITE) {
         if (NS_FAILED(CheckOverlapAndMergeObjectStores(storesWriting,
                                                        objectStores,
                                                        true, &dummy))) {
           NS_WARNING("Out of memory!");
         }
       }
-      else if (transaction->mMode == nsIIDBTransaction::READ_ONLY) {
+      else if (transaction->mMode == IDBTransaction::READ_ONLY) {
         if (NS_FAILED(CheckOverlapAndMergeObjectStores(storesReading,
                                                        objectStores,
                                                        true, &dummy))) {
           NS_WARNING("Out of memory!");
         }
       }
       else {
         NS_NOTREACHED("Unknown mode!");
@@ -353,29 +353,29 @@ TransactionThreadPool::TransactionCanRun
   }
 
   NS_ASSERTION(mode != IDBTransaction::VERSION_CHANGE, "How did we get here?");
 
   bool writeOverlap;
   nsresult rv =
     CheckOverlapAndMergeObjectStores(dbTransactionInfo->storesWriting,
                                      objectStoreNames,
-                                     mode == nsIIDBTransaction::READ_WRITE,
+                                     mode == IDBTransaction::READ_WRITE,
                                      &writeOverlap);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool readOverlap;
   rv = CheckOverlapAndMergeObjectStores(dbTransactionInfo->storesReading,
                                         objectStoreNames,
-                                        mode == nsIIDBTransaction::READ_ONLY,
+                                        mode == IDBTransaction::READ_ONLY,
                                         &readOverlap);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (writeOverlap ||
-      (readOverlap && mode == nsIIDBTransaction::READ_WRITE)) {
+      (readOverlap && mode == IDBTransaction::READ_WRITE)) {
     *aCanRun = false;
     *aExistingQueue = nsnull;
     return NS_OK;
   }
 
   *aCanRun = true;
   *aExistingQueue = nsnull;
   return NS_OK;
@@ -436,17 +436,17 @@ TransactionThreadPool::Dispatch(IDBTrans
     // Make a new struct for this transaction.
     autoDBTransactionInfo = new DatabaseTransactionInfo();
     dbTransactionInfo = autoDBTransactionInfo;
   }
 
   const nsTArray<nsString>& objectStoreNames = aTransaction->mObjectStoreNames;
 
   nsTArray<nsString>& storesInUse =
-    aTransaction->mMode == nsIIDBTransaction::READ_WRITE ?
+    aTransaction->mMode == IDBTransaction::READ_WRITE ?
     dbTransactionInfo->storesWriting :
     dbTransactionInfo->storesReading;
 
   if (!storesInUse.AppendElements(objectStoreNames)) {
     NS_WARNING("Out of memory!");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
--- a/dom/indexedDB/nsIIDBCursor.idl
+++ b/dom/indexedDB/nsIIDBCursor.idl
@@ -41,24 +41,21 @@
 
 interface nsIIDBRequest;
 
 /**
  * IDBCursor interface.  See
  * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
  * information.
  */
-[scriptable, builtinclass, uuid(9d5ddd43-132d-418e-81e8-17d64a6467a2)]
+[scriptable, builtinclass, uuid(01136b3a-d84c-487c-b929-f5d012346c44)]
 interface nsIIDBCursor : nsISupports
 {
-  const unsigned short NEXT = 0;
-  const unsigned short NEXT_NO_DUPLICATE = 1;
-  const unsigned short PREV = 2;
-  const unsigned short PREV_NO_DUPLICATE = 3;
-  readonly attribute unsigned short direction;
+  // "next", "nextunique", "prev" or "prevunique"
+  readonly attribute DOMString direction;
 
   readonly attribute nsISupports source;
 
   [implicit_jscontext]
   readonly attribute jsval key;
 
   [implicit_jscontext]
   readonly attribute jsval primaryKey;
--- a/dom/indexedDB/nsIIDBDatabase.idl
+++ b/dom/indexedDB/nsIIDBDatabase.idl
@@ -52,17 +52,17 @@ interface nsIIDBObjectStoreParameters : 
   attribute boolean autoIncrement;
 };
 
 /**
  * IDBDatabase interface.  See
  * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBDatabase
  * for more information.
  */
-[scriptable, builtinclass, uuid(bb877dff-ab5b-4ebb-9b3c-a7fa97cd4b51)]
+[scriptable, builtinclass, uuid(bedee48a-f47f-44f2-ba1e-d8fe595bbfee)]
 interface nsIIDBDatabase : nsISupports
 {
   readonly attribute DOMString name;
 
   readonly attribute unsigned long long version;
 
   readonly attribute nsIDOMDOMStringList objectStoreNames;
 
@@ -70,20 +70,21 @@ interface nsIIDBDatabase : nsISupports
   nsIIDBObjectStore
   createObjectStore([Null(Stringify)] in DOMString name,
                     /* nsIIDBObjectStoreParameters */
                     [optional /* none */] in jsval options);
 
   void
   deleteObjectStore([Null(Stringify)] in DOMString name);
 
+  // mode can be either "readonly" or "readwrite"
   [optional_argc, implicit_jscontext]
   nsIIDBTransaction
   transaction(in jsval storeNames, // js array of strings
-              [optional /* READ_ONLY */] in unsigned short mode);
+              [optional /* "readonly" */] in DOMString mode);
 
   void
   close();
 
   attribute nsIDOMEventListener onabort;
 
   attribute nsIDOMEventListener onerror;
 
--- a/dom/indexedDB/nsIIDBIndex.idl
+++ b/dom/indexedDB/nsIIDBIndex.idl
@@ -42,17 +42,17 @@
 interface nsIIDBObjectStore;
 interface nsIIDBRequest;
 
 /**
  * IDBIndex interface.  See
  * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBIndex for more
  * information.
  */
-[scriptable, builtinclass, uuid(233ec586-7b34-4263-b27e-a4991b757597)]
+[scriptable, builtinclass, uuid(a859747a-0f05-4dfb-8f42-05c61415d4e4)]
 interface nsIIDBIndex : nsISupports
 {
   readonly attribute DOMString name;
 
   readonly attribute DOMString storeName;
 
   [implicit_jscontext]
   readonly attribute jsval keyPath;
@@ -76,23 +76,25 @@ interface nsIIDBIndex : nsISupports
   getAll([optional /* null */] in jsval key,
          [optional /* unlimited */] in unsigned long limit);
 
   [implicit_jscontext, optional_argc]
   nsIIDBRequest
   getAllKeys([optional /* null */] in jsval key,
              [optional /* unlimited */] in unsigned long limit);
 
+  // direction can be "next", "nextunique", "prev" or "prevunique"
   [implicit_jscontext, optional_argc]
   nsIIDBRequest
   openCursor([optional /* null */] in jsval key,
-             [optional /* nsIIDBCursor::NEXT */] in unsigned short direction);
+             [optional /* "next" */] in DOMString direction);
 
+  // direction can be "next", "nextunique", "prev" or "prevunique"
   [implicit_jscontext, optional_argc]
   nsIIDBRequest
   openKeyCursor([optional /* null */] in jsval key,
-                [optional /* nsIIDBCursor::NEXT */] in unsigned short direction);
+                [optional /* "next" */] in DOMString direction);
 
   // Accepts null, a key value, or a nsIIDBKeyRange object.
   [implicit_jscontext, optional_argc]
   nsIIDBRequest
   count([optional] in jsval key);
 };
--- a/dom/indexedDB/nsIIDBObjectStore.idl
+++ b/dom/indexedDB/nsIIDBObjectStore.idl
@@ -52,17 +52,17 @@ interface nsIIDBIndexParameters : nsISup
   attribute boolean multiEntry;
 };
 
 /**
  * nsIIDBObjectStore interface.  See
  * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
  * for more information.
  */
-[scriptable, builtinclass, uuid(e0d308ea-b804-4962-918a-28ec0aa4e42b)]
+[scriptable, builtinclass, uuid(43157a3c-bed1-4ce7-98c0-11365b852560)]
 interface nsIIDBObjectStore : nsISupports
 {
   readonly attribute DOMString name;
 
   [implicit_jscontext]
   readonly attribute jsval keyPath;
 
   readonly attribute nsIDOMDOMStringList indexNames;
@@ -100,20 +100,21 @@ interface nsIIDBObjectStore : nsISupport
   delete(in jsval key);
 
   // Success fires IDBTransactionEvent, result == null
   nsIIDBRequest
   clear();
 
   // Success fires IDBTransactionEvent, result == IDBCursor or result == null if
   // no match.
+  // direction can be "next", "nextunique", "prev" or "prevunique"
   [implicit_jscontext, optional_argc]
   nsIIDBRequest
   openCursor([optional /* null */] in jsval range,
-             [optional /* NEXT */] in unsigned short direction);
+             [optional /* "next" */] in DOMString direction);
 
   [implicit_jscontext]
   nsIIDBIndex
   createIndex([Null(Stringify)] in DOMString name,
               in jsval keyPath,
               /* nsIIDBIndexParameters */
               [optional /* none */] in jsval options);
 
--- a/dom/indexedDB/nsIIDBRequest.idl
+++ b/dom/indexedDB/nsIIDBRequest.idl
@@ -43,22 +43,21 @@
 interface nsIDOMEventListener;
 interface nsIIDBTransaction;
 
 /**
  * IDBReqeust interface.  See
  * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBRequest for more
  * information.
  */
-[scriptable, builtinclass, uuid(a1e4a0ff-e0b2-431c-89cf-43b078189e27)]
+[scriptable, builtinclass, uuid(fe30ca60-bb90-4d68-af2f-4735f9228a54)]
 interface nsIIDBRequest : nsISupports
 {
-  const unsigned short LOADING = 1;
-  const unsigned short DONE = 2;
-  readonly attribute unsigned short readyState;
+  // "pending" or "done"
+  readonly attribute DOMString readyState;
 
   readonly attribute nsISupports source;
 
   readonly attribute nsIIDBTransaction transaction;
 
   readonly attribute jsval result;
 
   readonly attribute unsigned short errorCode;
--- a/dom/indexedDB/nsIIDBTransaction.idl
+++ b/dom/indexedDB/nsIIDBTransaction.idl
@@ -45,31 +45,23 @@ interface nsIIDBRequest;
 interface nsIIDBDatabase;
 interface nsIDOMDOMStringList;
 
 /**
  * IDBDTransaction interface.  See
  * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBTransaction
  * for more information.
  */
-[scriptable, builtinclass, uuid(4f25832d-de40-4c0b-a176-358d94384b19)]
+[scriptable, builtinclass, uuid(e4927c76-4f1f-4d7d-80ad-8186e1677da6)]
 interface nsIIDBTransaction : nsISupports
 {
   readonly attribute nsIIDBDatabase db;
 
-  const unsigned short INITIAL = 0;
-  const unsigned short LOADING = 1;
-  const unsigned short COMMITTING = 2;
-  const unsigned short DONE = 3;
-  readonly attribute unsigned short readyState;
-
-  const unsigned short READ_ONLY = 0;
-  const unsigned short READ_WRITE = 1;
-  const unsigned short VERSION_CHANGE = 2;
-  readonly attribute unsigned short mode;
+  // "readonly", "readwrite" or "versionchange"
+  readonly attribute DOMString mode;
 
   readonly attribute nsIDOMDOMStringList objectStoreNames;
 
   nsIIDBObjectStore
   objectStore([Null(Stringify)] in DOMString name);
 
   // Don't commit the transaction.
   void abort();
--- a/dom/indexedDB/test/browser_quotaPrompt.html
+++ b/dom/indexedDB/test/browser_quotaPrompt.html
@@ -2,23 +2,21 @@
   Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
   <head>
     <title>Indexed Database Test</title>
 
     <script type="text/javascript;version=1.7">
-      const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-
       let db;
       let version = window.location.href.charAt(window.location.href.length - 1);
 
       function onAddMore() {
-        let transaction = db.transaction("foo", READ_WRITE);
+        let transaction = db.transaction("foo", "readwrite");
 
         transaction.oncomplete = function(event) {
           setTimeout(testFinishedCallback, 0, "complete");
         }
         transaction.onabort = function(event) {
           setTimeout(testFinishedCallback, 0, "abort");
         }
 
--- a/dom/indexedDB/test/browser_quotaPromptDatabases.html
+++ b/dom/indexedDB/test/browser_quotaPromptDatabases.html
@@ -2,18 +2,16 @@
   Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
   <head>
     <title>Indexed Database Test</title>
 
     <script type="text/javascript;version=1.7">
-      const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-
       let db;
       let i = 0;
 
       function onAddMore() {
         const name = window.location.pathname + i++;
 
         let request = mozIndexedDB.open(name, 1);
         request.onerror = errorHandler;
--- a/dom/indexedDB/test/browser_quotaPromptDelete.html
+++ b/dom/indexedDB/test/browser_quotaPromptDelete.html
@@ -2,23 +2,21 @@
   Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
   <head>
     <title>Indexed Database Test</title>
 
     <script type="text/javascript;version=1.7">
-      const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-
       let db;
       let name = window.location.pathname;
 
       function onAddMore() {
-        let transaction = db.transaction("foo", READ_WRITE);
+        let transaction = db.transaction("foo", "readwrite");
 
         transaction.oncomplete = function(event) {
           setTimeout(testFinishedCallback, 0, "complete");
         }
         transaction.onabort = function(event) {
           setTimeout(testFinishedCallback, 0, "abort");
         }
 
--- a/dom/indexedDB/test/test_create_objectStore.html
+++ b/dom/indexedDB/test/test_create_objectStore.html
@@ -7,19 +7,16 @@
   <title>Indexed Database Property Test</title>
 
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 
   <script type="text/javascript;version=1.7">
     function testSteps()
     {
-      const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
-      const nsIIDBTransaction = Components.interfaces.nsIIDBTransaction;
-
       const name = window.location.pathname;
       const description = "My Test Database";
       const objectStoreInfo = [
         { name: "1", options: { keyPath: null } },
         { name: "2", options: { keyPath: null, autoIncrement: true } },
         { name: "3", options: { keyPath: null, autoIncrement: false } },
         { name: "4", options: { keyPath: null } },
         { name: "5", options: { keyPath: "foo" } },
@@ -95,19 +92,17 @@
         is(objectStore.name, name, "Bad name");
         is(objectStore.keyPath, info.options && info.options.keyPath ?
                                 info.options.keyPath : null,
            "Bad keyPath");
         if(objectStore.indexNames.length, 0, "Bad indexNames");
 
         ok(event.target.transaction, "event has a transaction");
         ok(event.target.transaction.db === db, "transaction has the right db");
-        is(event.target.transaction.readyState, nsIIDBTransaction.LOADING,
-           "transaction has the correct readyState");
-        is(event.target.transaction.mode, nsIIDBTransaction.VERSION_CHANGE,
+        is(event.target.transaction.mode, "versionchange",
            "transaction has the correct mode");
         is(event.target.transaction.objectStoreNames.length, index + 1,
            "transaction has correct objectStoreNames list");
         found = false;
         for (let j = 0; j < event.target.transaction.objectStoreNames.length;
              j++) {
           if (event.target.transaction.objectStoreNames.item(j) == name) {
             found = true;
--- a/dom/indexedDB/test/test_deleteDatabase.html
+++ b/dom/indexedDB/test/test_deleteDatabase.html
@@ -8,19 +8,16 @@
 
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 
   <script type="text/javascript;version=1.7">
 
   function testSteps()
   {
-    const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-    const VERSION_CHANGE = Components.interfaces.nsIIDBTransaction.VERSION_CHANGE;
-
     const name = window.location.pathname;
 
     ok(mozIndexedDB.deleteDatabase, "deleteDatabase function should exist!");
 
     let request = mozIndexedDB.open(name, 10);
     request.onerror = errorHandler;
     request.onsuccess = unexpectedSuccessHandler;
     request.onupgradeneeded = grabEventAndContinueHandler;
--- a/dom/indexedDB/test/test_deleteDatabase_interactions.html
+++ b/dom/indexedDB/test/test_deleteDatabase_interactions.html
@@ -8,19 +8,16 @@
 
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 
   <script type="text/javascript;version=1.7">
 
   function testSteps()
   {
-    const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-    const VERSION_CHANGE = Components.interfaces.nsIIDBTransaction.VERSION_CHANGE;
-
     const name = window.location.pathname;
 
     let request = mozIndexedDB.open(name, 10);
     request.onerror = errorHandler;
     request.onsuccess = unexpectedSuccessHandler;
     request.onupgradeneeded = grabEventAndContinueHandler;
 
     ok(request instanceof IDBOpenDBRequest, "Expect an IDBOpenDBRequest");
--- a/dom/indexedDB/test/test_readonly_transactions.html
+++ b/dom/indexedDB/test/test_readonly_transactions.html
@@ -7,19 +7,16 @@
   <title>Indexed Database Property Test</title>
 
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 
   <script type="text/javascript;version=1.7">
     function testSteps()
     {
-      const READ_ONLY = Components.interfaces.nsIIDBTransaction.READ_ONLY;
-      const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-
       const name = window.location.pathname;
       const description = "My Test Database";
       const osName = "foo";
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       request.onsuccess = grabEventAndContinueHandler;
@@ -29,92 +26,92 @@
       is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
 
       db.createObjectStore(osName, { autoIncrement: "true" });
 
       yield;
 
       let key1, key2;
 
-      request = db.transaction([osName], READ_WRITE)
+      request = db.transaction([osName], "readwrite")
                   .objectStore(osName)
                   .add({});
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
-        is(event.target.transaction.mode, READ_WRITE, "Correct mode");
+        is(event.target.transaction.mode, "readwrite", "Correct mode");
         key1 = event.target.result;
         testGenerator.next();
       }
       yield;
 
-      request = db.transaction(osName, READ_WRITE).objectStore(osName).add({});
+      request = db.transaction(osName, "readwrite").objectStore(osName).add({});
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
-        is(event.target.transaction.mode, READ_WRITE, "Correct mode");
+        is(event.target.transaction.mode, "readwrite", "Correct mode");
         key2 = event.target.result;
         testGenerator.next();
       }
       yield;
 
-      request = db.transaction([osName], READ_WRITE)
+      request = db.transaction([osName], "readwrite")
                   .objectStore(osName)
                   .put({}, key1);
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
-        is(event.target.transaction.mode, READ_WRITE, "Correct mode");
+        is(event.target.transaction.mode, "readwrite", "Correct mode");
         testGenerator.next();
       }
       yield;
 
-      request = db.transaction(osName, READ_WRITE)
+      request = db.transaction(osName, "readwrite")
                   .objectStore(osName)
                   .put({}, key2);
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
-        is(event.target.transaction.mode, READ_WRITE, "Correct mode");
+        is(event.target.transaction.mode, "readwrite", "Correct mode");
         testGenerator.next();
       }
       yield;
 
-      request = db.transaction([osName], READ_WRITE)
+      request = db.transaction([osName], "readwrite")
                   .objectStore(osName)
                   .put({}, key1);
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
-        is(event.target.transaction.mode, READ_WRITE, "Correct mode");
+        is(event.target.transaction.mode, "readwrite", "Correct mode");
         testGenerator.next();
       }
       yield;
 
-      request = db.transaction(osName, READ_WRITE)
+      request = db.transaction(osName, "readwrite")
                   .objectStore(osName)
                   .put({}, key1);
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
-        is(event.target.transaction.mode, READ_WRITE, "Correct mode");
+        is(event.target.transaction.mode, "readwrite", "Correct mode");
         testGenerator.next();
       }
       yield;
 
-      request = db.transaction([osName], READ_WRITE)
+      request = db.transaction([osName], "readwrite")
                   .objectStore(osName)
                   .delete(key1);
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
-        is(event.target.transaction.mode, READ_WRITE, "Correct mode");
+        is(event.target.transaction.mode, "readwrite", "Correct mode");
         testGenerator.next();
       }
       yield;
 
-      request = db.transaction(osName, READ_WRITE)
+      request = db.transaction(osName, "readwrite")
                   .objectStore(osName)
                   .delete(key2);
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
-        is(event.target.transaction.mode, READ_WRITE, "Correct mode");
+        is(event.target.transaction.mode, "readwrite", "Correct mode");
         testGenerator.next();
       }
       yield;
 
       try {
         request = db.transaction([osName]).objectStore(osName).add({});
         ok(false, "Adding to a readonly transaction should fail!");
       }
--- a/dom/indexedDB/test/unit/test_advance.js
+++ b/dom/indexedDB/test/unit/test_advance.js
@@ -139,17 +139,17 @@ function testSteps()
     }
   };
   yield;
 
   is(count, 0, "Saw all data");
 
   count = dataCount - 1;
 
-  getObjectStore().openCursor(null, IDBCursor.PREV).onsuccess = function(event) {
+  getObjectStore().openCursor(null, "prev").onsuccess = function(event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.primaryKey, count, "Got correct object");
       count--;
       if (count == dataCount - 2) {
         cursor.advance(10);
         count -= 9;
       }
@@ -162,17 +162,17 @@ function testSteps()
     }
   };
   yield;
 
   is(count, -1, "Saw all data");
 
   count = dataCount - 1;
 
-  getObjectStore().openCursor(null, IDBCursor.PREV).onsuccess = function(event) {
+  getObjectStore().openCursor(null, "prev").onsuccess = function(event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.primaryKey, count, "Got correct object");
       if (count == dataCount - 1) {
         cursor.advance(dataCount + 1);
       }
       else {
         ok(false, "Should never get here!");
--- a/dom/indexedDB/test/unit/test_clear.js
+++ b/dom/indexedDB/test/unit/test_clear.js
@@ -2,18 +2,16 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
-  const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
   const entryCount = 1000;
 
   let request = mozIndexedDB.open(name, 1, description);
   request.onerror = errorHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   let event = yield;
@@ -59,17 +57,17 @@ function testSteps()
   try {
     db.transaction("foo").objectStore("foo").clear();
     ok(false, "clear should throw on READ_ONLY transactions");
   }
   catch (e) {
     ok(true, "clear should throw on READ_ONLY transactions");
   }
 
-  request = db.transaction("foo", READ_WRITE).objectStore("foo").clear();
+  request = db.transaction("foo", "readwrite").objectStore("foo").clear();
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   ok(event.target.result === undefined, "Correct event.target.result");
   ok(request.result === undefined, "Correct request.result");
   ok(request === event.target, "Correct event.target");
 
@@ -79,17 +77,17 @@ function testSteps()
     let cursor = request.result;
     if (cursor) {
       ok(false, "Shouldn't have any entries");
     }
     continueToNextStep();
   }
   yield;
 
-  request = db.transaction("foo", READ_WRITE).objectStore("foo").add({});
+  request = db.transaction("foo", "readwrite").objectStore("foo").add({});
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   isnot(event.target.result, firstKey, "Got a different key");
 
   finishTest();
   yield;
--- a/dom/indexedDB/test/unit/test_create_index.js
+++ b/dom/indexedDB/test/unit/test_create_index.js
@@ -2,19 +2,16 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
-  const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
-  const nsIIDBTransaction = Components.interfaces.nsIIDBTransaction;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
   const objectStoreInfo = [
     { name: "a", options: { keyPath: "id", autoIncrement: true } },
     { name: "b", options: { keyPath: "id", autoIncrement: false } },
   ];
   const indexInfo = [
     { name: "1", keyPath: "unique_value", options: { unique: true } },
@@ -104,19 +101,17 @@ function testSteps()
           break;
         }
       }
       ok(found, "Name is on objectStore.indexNames");
 
       ok(event.target.transaction, "event has a transaction");
       ok(event.target.transaction.db === db,
          "transaction has the right db");
-      is(event.target.transaction.readyState, nsIIDBTransaction.LOADING,
-         "transaction has the correct readyState");
-      is(event.target.transaction.mode, nsIIDBTransaction.VERSION_CHANGE,
+      is(event.target.transaction.mode, "versionchange",
          "transaction has the correct mode");
       is(event.target.transaction.objectStoreNames.length, i + 1,
          "transaction only has one object store");
       is(event.target.transaction.objectStoreNames.item(0), objectStoreName,
          "transaction has the correct object store");
     }
   }
 
--- a/dom/indexedDB/test/unit/test_create_objectStore.js
+++ b/dom/indexedDB/test/unit/test_create_objectStore.js
@@ -2,19 +2,16 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
-  const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
-  const nsIIDBTransaction = Components.interfaces.nsIIDBTransaction;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
   const objectStoreInfo = [
     { name: "1", options: { keyPath: null } },
     { name: "2", options: { keyPath: null, autoIncrement: true } },
     { name: "3", options: { keyPath: null, autoIncrement: false } },
     { name: "4", options: { keyPath: null } },
     { name: "5", options: { keyPath: "foo" } },
@@ -82,19 +79,17 @@ function testSteps()
     is(objectStore.name, name, "Bad name");
     is(objectStore.keyPath, info.options && info.options.keyPath ?
                             info.options.keyPath : null,
        "Bad keyPath");
     if(objectStore.indexNames.length, 0, "Bad indexNames");
 
     ok(event.target.transaction, "event has a transaction");
     ok(event.target.transaction.db === db, "transaction has the right db");
-    is(event.target.transaction.readyState, nsIIDBTransaction.LOADING,
-       "transaction has the correct readyState");
-    is(event.target.transaction.mode, nsIIDBTransaction.VERSION_CHANGE,
+    is(event.target.transaction.mode, "versionchange",
        "transaction has the correct mode");
     is(event.target.transaction.objectStoreNames.length, index + 1,
        "transaction has correct objectStoreNames list");
     found = false;
     for (let j = 0; j < event.target.transaction.objectStoreNames.length;
          j++) {
       if (event.target.transaction.objectStoreNames.item(j) == name) {
         found = true;
--- a/dom/indexedDB/test/unit/test_cursor_mutation.js
+++ b/dom/indexedDB/test/unit/test_cursor_mutation.js
@@ -66,17 +66,17 @@ function testSteps()
   is(count, objectStoreData.length - 1, "Good initial count");
   is(sawAdded, false, "Didn't see item that is about to be added");
   is(sawRemoved, true, "Saw item that is about to be removed");
 
   count = 0;
   sawAdded = false;
   sawRemoved = false;
 
-  db.transaction("foo", IDBTransaction.READ_WRITE).objectStore("foo")
+  db.transaction("foo", "readwrite").objectStore("foo")
     .index("name").openCursor().onsuccess = function(event) {
       event.target.transaction.oncomplete = continueToNextStep;
       let cursor = event.target.result;
       if (cursor) {
         if (cursor.value.name == objectStoreData[0].name) {
           sawRemoved = true;
         }
         if (cursor.value.name ==
--- a/dom/indexedDB/test/unit/test_cursor_update_updates_indexes.js
+++ b/dom/indexedDB/test/unit/test_cursor_update_updates_indexes.js
@@ -2,19 +2,16 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
-  const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
-  const nsIIDBTransaction = Components.interfaces.nsIIDBTransaction;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
   const START_DATA = "hi";
   const END_DATA = "bye";
   const objectStoreInfo = [
     { name: "1", options: { keyPath: null }, key: 1,
       entry: { data: START_DATA } },
     { name: "2", options: { keyPath: "foo" },
--- a/dom/indexedDB/test/unit/test_cursors.js
+++ b/dom/indexedDB/test/unit/test_cursors.js
@@ -281,17 +281,17 @@ function testSteps()
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   keyIndex = 0;
 
   let gotRemoveEvent = false;
   let retval = false;
 
-  request = objectStore.openCursor(null, IDBCursor.NEXT);
+  request = objectStore.openCursor(null, "next");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, sortedKeys[keyIndex], "Correct key");
       is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
       is(cursor.value, "foo", "Correct value");
 
@@ -326,17 +326,17 @@ function testSteps()
 
   request = objectStore.add("foo", sortedKeys[4]);
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   keyIndex = sortedKeys.length - 1;
 
-  request = objectStore.openCursor(null, IDBCursor.PREV);
+  request = objectStore.openCursor(null, "prev");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, sortedKeys[keyIndex], "Correct key");
       is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
       is(cursor.value, "foo", "Correct value");
 
--- a/dom/indexedDB/test/unit/test_index_empty_keyPath.js
+++ b/dom/indexedDB/test/unit/test_index_empty_keyPath.js
@@ -38,17 +38,17 @@ function testSteps()
     }
   }
   event = yield; // testGenerator.send
 
   // Now create the index.
   objectStore.createIndex("set", "", { unique: true });
   yield; // success
 
-  let trans = db.transaction("data", IDBTransaction.READ_WRITE);
+  let trans = db.transaction("data", "readwrite");
   objectStore = trans.objectStore("data");
   index = objectStore.index("set");
 
   let request = index.get("bar");
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   
   let event = yield;
--- a/dom/indexedDB/test/unit/test_index_object_cursors.js
+++ b/dom/indexedDB/test/unit/test_index_object_cursors.js
@@ -52,17 +52,17 @@ function testSteps()
   for (let objectStoreIndex in objectStoreData) {
     const info = objectStoreData[objectStoreIndex];
 
     for (let indexIndex in indexData) {
       const objectStoreName = objectStoreData[objectStoreIndex].name;
       const indexName = indexData[indexIndex].name;
 
       let objectStore =
-        db.transaction(objectStoreName, IDBTransaction.READ_WRITE)
+        db.transaction(objectStoreName, "readwrite")
           .objectStore(objectStoreName);
       ok(true, "Got objectStore " + objectStoreName);
 
       for (let dataIndex in data) {
         const obj = data[dataIndex];
         let key;
         if (!info.options.keyPath && !info.options.autoIncrement) {
           key = obj.ss;
@@ -128,17 +128,17 @@ function testSteps()
 
         cursor.continue();
         keyIndex++;
       };
       yield;
 
       is(keyIndex, 1, "Saw all the items");
 
-      db.transaction(objectStoreName, IDBTransaction.READ_WRITE)
+      db.transaction(objectStoreName, "readwrite")
         .objectStore(objectStoreName).clear()
         .onsuccess = continueToNextStep;
       yield;
     }
   }
 
   finishTest();
   yield;
--- a/dom/indexedDB/test/unit/test_index_update_delete.js
+++ b/dom/indexedDB/test/unit/test_index_update_delete.js
@@ -47,17 +47,17 @@ function testSteps()
     let event = yield;
 
     is(event.target.result, 20, "Correct number of entries in objectStore");
 
     let objectStoreCount = event.target.result;
     let indexCount = event.target.result;
 
     for each (let unique in [false, true]) {
-      let index = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
+      let index = db.transaction(autoIncrement, "readwrite")
                     .objectStore(autoIncrement)
                     .index(unique);
 
       index.count().onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       is(event.target.result, indexCount,
          "Correct number of entries in index");
@@ -81,17 +81,17 @@ function testSteps()
           continueToNextStep();
         }
       }
       yield;
 
       is(sawEntry, true, "Saw entry for key value " + modifiedEntry);
 
       // Recount index. Shouldn't change.
-      index = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
+      index = db.transaction(autoIncrement, "readwrite")
                 .objectStore(autoIncrement)
                 .index(unique);
 
       index.count().onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       is(event.target.result, indexCount,
          "Correct number of entries in index");
@@ -116,17 +116,17 @@ function testSteps()
           continueToNextStep();
         }
       }
       yield;
 
       is(sawEntry, true, "Saw entry for key value " + modifiedEntry);
 
       // Recount objectStore. Should be unchanged.
-      objectStore = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
+      objectStore = db.transaction(autoIncrement, "readwrite")
                       .objectStore(autoIncrement);
 
       objectStore.count().onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       is(event.target.result, objectStoreCount,
          "Correct number of entries in objectStore");
 
--- a/dom/indexedDB/test/unit/test_indexes.js
+++ b/dom/indexedDB/test/unit/test_indexes.js
@@ -4,23 +4,16 @@
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
   const CONSTRAINT_ERR =
     Components.interfaces.nsIIDBDatabaseException.CONSTRAINT_ERR;
-  const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-  const NEXT = Components.interfaces.nsIIDBCursor.NEXT;
-  const PREV = Components.interfaces.nsIIDBCursor.PREV;
-  const NEXT_NO_DUPLICATE =
-    Components.interfaces.nsIIDBCursor.NEXT_NO_DUPLICATE;
-  const PREV_NO_DUPLICATE =
-    Components.interfaces.nsIIDBCursor.PREV_NO_DUPLICATE;
 
   const name = this.window ? this.window ? window.location.pathname : "Splendid Test" : "Splendid Test";
   const description = "My Test Database";
 
   const objectStoreName = "People";
 
   const objectStoreData = [
     { key: "237-23-7732", value: { name: "Bob", height: 60, weight: 120 } },
@@ -162,17 +155,17 @@ function testSteps()
   yield;
 
   is(keyIndex, objectStoreData.length, "Saw all the expected keys");
 
   ok(true, "Test group 2");
 
   keyIndex = 0;
 
-  request = objectStore.index("weight").openKeyCursor(null, NEXT);
+  request = objectStore.index("weight").openKeyCursor(null, "next");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataWeightSort[keyIndex].value.weight,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataWeightSort[keyIndex].key,
          "Correct value");
@@ -190,29 +183,29 @@ function testSteps()
       testGenerator.next();
     }
   }
   yield;
 
   is(keyIndex, objectStoreData.length - 1, "Saw all the expected keys");
 
   // Check that the name index enforces its unique constraint.
-  objectStore = db.transaction(objectStoreName, READ_WRITE)
+  objectStore = db.transaction(objectStoreName, "readwrite")
                   .objectStore(objectStoreName);
   request = objectStore.add({ name: "Bob", height: 62, weight: 170 },
                             "237-23-7738");
   request.onerror = new ExpectError(CONSTRAINT_ERR);
   request.onsuccess = unexpectedSuccessHandler;
   event = yield;
 
   ok(true, "Test group 3");
 
   keyIndex = objectStoreDataNameSort.length - 1;
 
-  request = objectStore.index("name").openKeyCursor(null, PREV);
+  request = objectStore.index("name").openKeyCursor(null, "prev");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataNameSort[keyIndex].value.name,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataNameSort[keyIndex].key,
          "Correct value");
@@ -518,17 +511,17 @@ function testSteps()
   yield;
 
   is(keyIndex, objectStoreDataNameSort.length, "Saw all the expected keys");
 
   ok(true, "Test group 14");
 
   keyIndex = objectStoreDataNameSort.length - 1;
 
-  request = objectStore.index("name").openCursor(null, PREV);
+  request = objectStore.index("name").openCursor(null, "prev");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataNameSort[keyIndex].value.name,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataNameSort[keyIndex].key,
          "Correct primary key");
@@ -778,17 +771,17 @@ function testSteps()
 
   is(keyIndex, 4, "Saw all the expected keys");
 
   ok(true, "Test group 19");
 
   keyIndex = 4;
   keyRange = IDBKeyRange.bound("Bob", "Ron");
 
-  request = objectStore.index("name").openCursor(keyRange, PREV);
+  request = objectStore.index("name").openCursor(keyRange, "prev");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataNameSort[keyIndex].value.name,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataNameSort[keyIndex].key,
          "Correct primary key");
@@ -827,21 +820,21 @@ function testSteps()
     }
   }
   yield;
 
   is(keyIndex, 0, "Saw all the expected keys");
 
   ok(true, "Test group 20");
 
-  // Test NEXT_NO_DUPLICATE
+  // Test "nextunique"
   keyIndex = 3;
   keyRange = IDBKeyRange.only(65);
 
-  request = objectStore.index("height").openKeyCursor(keyRange, NEXT);
+  request = objectStore.index("height").openKeyCursor(keyRange, "next");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataHeightSort[keyIndex].key,
          "Correct value");
@@ -858,17 +851,17 @@ function testSteps()
   is(keyIndex, 5, "Saw all the expected keys");
 
   ok(true, "Test group 21");
 
   keyIndex = 3;
   keyRange = IDBKeyRange.only(65);
 
   request = objectStore.index("height").openKeyCursor(keyRange,
-                                                      NEXT_NO_DUPLICATE);
+                                                      "nextunique");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataHeightSort[keyIndex].key,
          "Correct value");
@@ -883,17 +876,17 @@ function testSteps()
   yield;
 
   is(keyIndex, 4, "Saw all the expected keys");
 
   ok(true, "Test group 21.5");
 
   keyIndex = 5;
 
-  request = objectStore.index("height").openKeyCursor(null, PREV);
+  request = objectStore.index("height").openKeyCursor(null, "prev");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataHeightSort[keyIndex].key,
          "Correct value");
@@ -909,17 +902,17 @@ function testSteps()
 
   is(keyIndex, -1, "Saw all the expected keys");
 
   ok(true, "Test group 22");
 
   keyIndex = 5;
 
   request = objectStore.index("height").openKeyCursor(null,
-                                                      PREV_NO_DUPLICATE);
+                                                      "prevunique");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataHeightSort[keyIndex].key,
          "Correct value");
@@ -938,17 +931,17 @@ function testSteps()
 
   is(keyIndex, -1, "Saw all the expected keys");
 
   ok(true, "Test group 23");
 
   keyIndex = 3;
   keyRange = IDBKeyRange.only(65);
 
-  request = objectStore.index("height").openCursor(keyRange, NEXT);
+  request = objectStore.index("height").openCursor(keyRange, "next");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataHeightSort[keyIndex].key,
          "Correct primary key");
@@ -975,17 +968,17 @@ function testSteps()
   is(keyIndex, 5, "Saw all the expected keys");
 
   ok(true, "Test group 24");
 
   keyIndex = 3;
   keyRange = IDBKeyRange.only(65);
 
   request = objectStore.index("height").openCursor(keyRange,
-                                                   NEXT_NO_DUPLICATE);
+                                                   "nextunique");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataHeightSort[keyIndex].key,
          "Correct primary key");
@@ -1010,17 +1003,17 @@ function testSteps()
   yield;
 
   is(keyIndex, 4, "Saw all the expected keys");
 
   ok(true, "Test group 24.5");
 
   keyIndex = 5;
 
-  request = objectStore.index("height").openCursor(null, PREV);
+  request = objectStore.index("height").openCursor(null, "prev");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataHeightSort[keyIndex].key,
          "Correct primary key");
@@ -1046,17 +1039,17 @@ function testSteps()
 
   is(keyIndex, -1, "Saw all the expected keys");
 
   ok(true, "Test group 25");
 
   keyIndex = 5;
 
   request = objectStore.index("height").openCursor(null,
-                                                   PREV_NO_DUPLICATE);
+                                                   "prevunique");
   request.onerror = errorHandler;
   request.onsuccess = function (event) {
     let cursor = event.target.result;
     if (cursor) {
       is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
          "Correct key");
       is(cursor.primaryKey, objectStoreDataHeightSort[keyIndex].key,
          "Correct primary key");
--- a/dom/indexedDB/test/unit/test_indexes_bad_values.js
+++ b/dom/indexedDB/test/unit/test_indexes_bad_values.js
@@ -4,17 +4,16 @@
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
   const CONSTRAINT_ERR =
     Components.interfaces.nsIIDBDatabaseException.CONSTRAINT_ERR;
-  const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
 
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
 
   const objectStoreName = "People";
 
   const objectStoreData = [
     { key: "237-23-7732", value: { name: "Bob", height: 60, weight: 120 } },
--- a/dom/indexedDB/test/unit/test_keys.js
+++ b/dom/indexedDB/test/unit/test_keys.js
@@ -3,17 +3,17 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
   const dbname = this.window ? window.location.pathname : "Splendid Test";
-  const RW = IDBTransaction.READ_WRITE
+  const RW = "readwrite"
   let c1 = 1;
   let c2 = 1;
 
   let openRequest = mozIndexedDB.open(dbname, 1);
   openRequest.onerror = errorHandler;
   openRequest.onupgradeneeded = grabEventAndContinueHandler;
   openRequest.onsuccess = unexpectedSuccessHandler;
   let event = yield;
--- a/dom/indexedDB/test/unit/test_multientry.js
+++ b/dom/indexedDB/test/unit/test_multientry.js
@@ -202,17 +202,17 @@ function testSteps()
     is(req.result, undefined, "exhausted temp index");
     store.deleteIndex("temp index");
   }
 
 
   openRequest.onsuccess = grabEventAndContinueHandler;
   yield;
 
-  let trans = db.transaction(["mystore"], IDBTransaction.READ_WRITE);
+  let trans = db.transaction(["mystore"], "readwrite");
   store = trans.objectStore("mystore");
   index = store.index("myindex");
   is(index.multiEntry, true, "index still is multiEntry");
   trans.oncomplete = grabEventAndContinueHandler;
   yield;
 
   finishTest();
   yield;
--- a/dom/indexedDB/test/unit/test_odd_result_order.js
+++ b/dom/indexedDB/test/unit/test_odd_result_order.js
@@ -22,17 +22,17 @@ function testSteps()
 
   let objectStore = db.createObjectStore("foo", { keyPath: "key",
                                                   autoIncrement: true });
   let index = objectStore.createIndex("foo", "index");
 
   event.target.onsuccess = continueToNextStep;
   yield;
 
-  objectStore = db.transaction("foo", IDBTransaction.READ_WRITE)
+  objectStore = db.transaction("foo", "readwrite")
                   .objectStore("foo");
   request = objectStore.add(data);
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   let key;
   executeSoon(function() {
     key = request.result;
@@ -51,17 +51,17 @@ function testSteps()
     obj = event.target.result;
     continueToNextStep();
   });
   yield;
 
   is(obj.key, data.key, "Got the right key");
   is(obj.index, data.index, "Got the right property value");
 
-  objectStore = db.transaction("foo", IDBTransaction.READ_WRITE)
+  objectStore = db.transaction("foo", "readwrite")
                   .objectStore("foo");
   request = objectStore.delete(data.key);
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   key = undefined;
   executeSoon(function() {
     key = request.result;
--- a/dom/indexedDB/test/unit/test_optionalArguments.js
+++ b/dom/indexedDB/test/unit/test_optionalArguments.js
@@ -147,17 +147,17 @@ function testSteps()
 
   keyRange = IDBKeyRange.bound(data[2].ssn, data[4].ssn, true);
 
   objectStore.get(keyRange).onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   is(event.target.result.name, data[3].name, "Correct data");
 
-  objectStore = db.transaction(osName, IDBTransaction.READ_WRITE)
+  objectStore = db.transaction(osName, "readwrite")
                   .objectStore(osName);
 
   try {
     objectStore.delete();
     ok(false, "Delete with unspecified arg should have thrown");
   }
   catch(e) {
     ok(true, "Delete with unspecified arg should have thrown");
--- a/dom/indexedDB/test/unit/test_overlapping_transactions.js
+++ b/dom/indexedDB/test/unit/test_overlapping_transactions.js
@@ -2,18 +2,16 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
-  const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
   const objectStores = [ "foo", "bar" ];
 
   let request = mozIndexedDB.open(name, 1, description);
   request.onerror = errorHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   let event = yield;
@@ -28,57 +26,57 @@ function testSteps()
   let event = yield;
 
   is(db.objectStoreNames.length, objectStores.length,
      "Correct objectStoreNames list");
 
   for (let i = 0; i < 50; i++) {
     let stepNumber = 0;
 
-    request = db.transaction(["foo"], READ_WRITE)
+    request = db.transaction(["foo"], "readwrite")
                 .objectStore("foo")
                 .add({});
     request.onerror = errorHandler;
     request.onsuccess = function(event) {
       is(stepNumber, 1, "This callback came first");
       stepNumber++;
       event.target.transaction.oncomplete = grabEventAndContinueHandler;
     }
 
-    request = db.transaction(["foo"], READ_WRITE)
+    request = db.transaction(["foo"], "readwrite")
                 .objectStore("foo")
                 .add({});
     request.onerror = errorHandler;
     request.onsuccess = function(event) {
       is(stepNumber, 2, "This callback came second");
       stepNumber++;
       event.target.transaction.oncomplete = grabEventAndContinueHandler;      
     }
 
-    request = db.transaction(["foo", "bar"], READ_WRITE)
+    request = db.transaction(["foo", "bar"], "readwrite")
                 .objectStore("bar")
                 .add({});
     request.onerror = errorHandler;
     request.onsuccess = function(event) {
       is(stepNumber, 3, "This callback came third");
       stepNumber++;
       event.target.transaction.oncomplete = grabEventAndContinueHandler;      
     }
 
-    request = db.transaction(["foo", "bar"], READ_WRITE)
+    request = db.transaction(["foo", "bar"], "readwrite")
                 .objectStore("bar")
                 .add({});
     request.onerror = errorHandler;
     request.onsuccess = function(event) {
       is(stepNumber, 4, "This callback came fourth");
       stepNumber++;
       event.target.transaction.oncomplete = grabEventAndContinueHandler;
     }
 
-    request = db.transaction(["bar"], READ_WRITE)
+    request = db.transaction(["bar"], "readwrite")
                 .objectStore("bar")
                 .add({});
     request.onerror = errorHandler;
     request.onsuccess = function(event) {
       is(stepNumber, 5, "This callback came fifth");
       stepNumber++;
       event.target.transaction.oncomplete = grabEventAndContinueHandler;
     }
--- a/dom/indexedDB/test/unit/test_request_readyState.js
+++ b/dom/indexedDB/test/unit/test_request_readyState.js
@@ -5,47 +5,44 @@
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
 
-  const LOADING = Components.interfaces.nsIIDBRequest.LOADING;
-  const DONE = Components.interfaces.nsIIDBRequest.DONE;
-
   let request = mozIndexedDB.open(name, 1, description);
-  is(request.readyState, LOADING, "Correct readyState");
+  is(request.readyState, "pending", "Correct readyState");
 
   request.onerror = errorHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   let event = yield;
 
-  is(request.readyState, DONE, "Correct readyState");
+  is(request.readyState, "done", "Correct readyState");
 
   let db = event.target.result;
 
   let objectStore = db.createObjectStore("foo");
   let key = 10;
 
   request = objectStore.add({}, key);
-  is(request.readyState, LOADING, "Correct readyState");
+  is(request.readyState, "pending", "Correct readyState");
 
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
-  is(request.readyState, DONE, "Correct readyState");
+  is(request.readyState, "done", "Correct readyState");
   is(event.target.result, key, "Correct key");
 
   request = objectStore.get(key);
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
-  is(request.readyState, LOADING, "Correct readyState");
+  is(request.readyState, "pending", "Correct readyState");
   event = yield;
 
   ok(event.target.result, "Got something");
-  is(request.readyState, DONE, "Correct readyState");
+  is(request.readyState, "done", "Correct readyState");
 
   finishTest();
   yield;
 }
--- a/dom/indexedDB/test/unit/test_setVersion.js
+++ b/dom/indexedDB/test/unit/test_setVersion.js
@@ -2,19 +2,16 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
-  const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-  const VERSION_CHANGE = Components.interfaces.nsIIDBTransaction.VERSION_CHANGE;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
 
   let request = mozIndexedDB.open(name, 1, description);
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   let event = yield;
 
@@ -36,17 +33,17 @@ function testSteps()
     let request = mozIndexedDB.open(name, version, description);
     request.onerror = errorHandler;
     request.onupgradeneeded = grabEventAndContinueHandler;
     let event = yield;
 
     let db = event.target.result;
 
     is(db.version, version, "Database version number updated correctly");
-    is(event.target.transaction.mode, VERSION_CHANGE, "Correct mode");
+    is(event.target.transaction.mode, "versionchange", "Correct mode");
 
     executeSoon(function() { testGenerator.next(); });
     yield;
     db.close();
   }
 
   finishTest();
   yield;
--- a/dom/indexedDB/test/unit/test_setVersion_abort.js
+++ b/dom/indexedDB/test/unit/test_setVersion_abort.js
@@ -2,19 +2,16 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
-  const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-  const VERSION_CHANGE = Components.interfaces.nsIIDBTransaction.VERSION_CHANGE;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
 
   let request = mozIndexedDB.open(name, 1, description);
   request.onerror = grabEventAndContinueHandler;
   request.onsuccess = unexpectedSuccessHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   let event = yield;
--- a/dom/indexedDB/test/unit/test_setVersion_events.js
+++ b/dom/indexedDB/test/unit/test_setVersion_events.js
@@ -52,17 +52,17 @@ function testSteps()
   request.onupgradeneeded = grabEventAndContinueHandler;
   request.onblocked = errorHandler;
   event = yield;
 
   // Test the upgradeneeded event.
   ok(event instanceof IDBVersionChangeEvent, "Event is of the right type");
   ok(event.target.result instanceof IDBDatabase, "Good result");
   db2 = event.target.result;
-  is(event.target.transaction.mode, IDBTransaction.VERSION_CHANGE,
+  is(event.target.transaction.mode, "versionchange",
      "Correct mode");
   is(db2.version, 2, "Correct db version");
   is(event.oldVersion, 1, "Correct event oldVersion");
   is(event.newVersion, 2, "Correct event newVersion");
 
   request.onupgradeneeded = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
@@ -122,17 +122,17 @@ function testSteps()
   request.onsuccess = errorHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   request.onblocked = errorHandler;
 
   event = yield;
 
   ok(event instanceof IDBVersionChangeEvent, "Event is of the right type");
   ok(event.target.result instanceof IDBDatabase, "Good result");
-  is(event.target.transaction.mode, IDBTransaction.VERSION_CHANGE,
+  is(event.target.transaction.mode, "versionchange",
      "Correct mode");
   is(event.oldVersion, 3, "Correct event oldVersion");
   is(event.newVersion, 4, "Correct event newVersion");
 
   request.onsuccess = grabEventAndContinueHandler;
 
   event = yield;
   ok(event.target.result instanceof IDBDatabase, "Expect a database here");
--- a/dom/indexedDB/test/unit/test_transaction_abort.js
+++ b/dom/indexedDB/test/unit/test_transaction_abort.js
@@ -8,24 +8,16 @@ var testGenerator = testSteps();
 var abortFired = false;
 
 function abortListener() { abortFired = true; }
 
 function testSteps()
 {
   const Ci = Components.interfaces;
 
-  const INITIAL = Ci.nsIIDBTransaction.INITIAL;
-  const LOADING = Ci.nsIIDBTransaction.LOADING;
-  const COMMITTING = Ci.nsIIDBTransaction.COMMITTING;
-  const DONE = Ci.nsIIDBTransaction.DONE;
-  const READ_ONLY = Ci.nsIIDBTransaction.READ_ONLY;
-  const READ_WRITE = Ci.nsIIDBTransaction.READ_WRITE;
-  const VERSION_CHANGE = Ci.nsIIDBTransaction.VERSION_CHANGE;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
 
 
   let request = mozIndexedDB.open(name, 1, description);
   request.onerror = errorHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   request.onsuccess = grabEventAndContinueHandler;
@@ -38,18 +30,17 @@ function testSteps()
   let objectStore;
   let index;
 
   transaction = event.target.transaction;
   objectStore = db.createObjectStore("foo", { autoIncrement: true });
   index = objectStore.createIndex("fooindex", "indexKey", { unique: true });
 
   is(transaction.db, db, "Correct database");
-  is(transaction.readyState, LOADING, "Correct readyState");
-  is(transaction.mode, VERSION_CHANGE, "Correct mode");
+  is(transaction.mode, "versionchange", "Correct mode");
   is(transaction.objectStoreNames.length, 1, "Correct names length");
   is(transaction.objectStoreNames.item(0), "foo", "Correct name");
   is(transaction.objectStore("foo"), objectStore, "Can get stores");
   is(transaction.oncomplete, null, "No complete listener");
   is(transaction.onabort, null, "No abort listener");
 
   is(objectStore.name, "foo", "Correct name");
   is(objectStore.keyPath, null, "Correct keyPath");
@@ -58,18 +49,17 @@ function testSteps()
   is(objectStore.indexNames[0], "fooindex", "Correct indexNames name");
   is(objectStore.index("fooindex"), index, "Can get index");
 
   // Wait until it's complete!
   transaction.oncomplete = grabEventAndContinueHandler;
   event = yield;
 
   is(transaction.db, db, "Correct database");
-  is(transaction.readyState, DONE, "Correct readyState");
-  is(transaction.mode, VERSION_CHANGE, "Correct mode");
+  is(transaction.mode, "versionchange", "Correct mode");
   is(transaction.objectStoreNames.length, 1, "Correct names length");
   is(transaction.objectStoreNames.item(0), "foo", "Correct name");
   is(transaction.onabort, null, "No abort listener");
 
   try {
     is(transaction.objectStore("foo").name, "foo", "Can't get stores");
     ok(false, "Should have thrown");
   }
@@ -160,46 +150,44 @@ function testSteps()
     ok(false, "Should have thrown");
   }
   catch (e) {
     ok(true, "RemoveIndex threw");
   }
 
   yield;
 
-  request = db.transaction("foo", READ_WRITE).objectStore("foo").add({});
+  request = db.transaction("foo", "readwrite").objectStore("foo").add({});
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   event.target.transaction.onabort = function(event) {
     ok(false, "Shouldn't see an abort event!");
   };
   event.target.transaction.oncomplete = grabEventAndContinueHandler;
   event = yield;
 
   is(event.type, "complete", "Right kind of event");
 
   let key;
 
-  request = db.transaction("foo", READ_WRITE).objectStore("foo").add({});
+  request = db.transaction("foo", "readwrite").objectStore("foo").add({});
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   key = event.target.result;
 
   event.target.transaction.onabort = grabEventAndContinueHandler;
   event.target.transaction.oncomplete = function(event) {
     ok(false, "Shouldn't see a complete event here!");
   };
 
-  is(event.target.transaction.readyState, LOADING, "Correct readyState");
   event.target.transaction.abort();
-  is(event.target.transaction.readyState, DONE, "Correct readyState");
 
   event = yield;
 
   is(event.type, "abort", "Right kind of event");
 
   request = db.transaction("foo").objectStore("foo").get(key);
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
@@ -213,17 +201,17 @@ function testSteps()
   let keys = [];
   let abortEventCount = 0;
   function abortErrorHandler(event) {
       is(event.target.errorCode, IDBDatabaseException.ABORT_ERR,
          "Good code");
       abortEventCount++;
       event.preventDefault();
   };
-  objectStore = db.transaction("foo", READ_WRITE).objectStore("foo");
+  objectStore = db.transaction("foo", "readwrite").objectStore("foo");
 
   for (let i = 0; i < 10; i++) {
     request = objectStore.add({});
     request.onerror = abortErrorHandler;
     request.onsuccess = function(event) {
       keys.push(event.target.result);
       if (keys.length == 5) {
         event.target.transaction.onabort = grabEventAndContinueHandler;
@@ -242,17 +230,17 @@ function testSteps()
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     event = yield;
 
     is(event.target.result, undefined, "Object was removed by abort");
   }
 
   // Set up some predictible data
-  transaction = db.transaction("foo", READ_WRITE);
+  transaction = db.transaction("foo", "readwrite");
   objectStore = transaction.objectStore("foo");
   objectStore.clear();
   objectStore.add({}, 1);
   objectStore.add({}, 2);
   request = objectStore.add({}, 1);
   request.onsuccess = function() {
     ok(false, "inserting duplicate key should fail");
   }
@@ -264,118 +252,106 @@ function testSteps()
   yield;
 
   // Check when aborting is allowed
   abortEventCount = 0;
   let expectedAbortEventCount = 0;
 
   // During INITIAL
   transaction = db.transaction("foo");
-  is(transaction.readyState, INITIAL, "in INITIAL state");
   transaction.abort();
-  is(transaction.readyState, DONE, "in DONE state after abort()");
   try {
     transaction.abort();
     ok(false, "second abort should throw an error");
   }
   catch (ex) {
     ok(true, "second abort should throw an error");
   }
 
   // During LOADING
   transaction = db.transaction("foo");
   transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
   expectedAbortEventCount++;
-  is(transaction.readyState, LOADING, "in LOADING state");
   transaction.abort();
-  is(transaction.readyState, DONE, "in DONE state after abort()");
   try {
     transaction.abort();
     ok(false, "second abort should throw an error");
   }
   catch (ex) {
     ok(true, "second abort should throw an error");
   }
 
   // During LOADING from callback
   transaction = db.transaction("foo");
   transaction.objectStore("foo").get(1).onsuccess = grabEventAndContinueHandler;
   event = yield;
   transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
   expectedAbortEventCount++
-  is(transaction.readyState, LOADING, "in LOADING state");
   transaction.abort();
-  is(transaction.readyState, DONE, "in DONE state after abort()");
   try {
     transaction.abort();
     ok(false, "second abort should throw an error");
   }
   catch (ex) {
     ok(true, "second abort should throw an error");
   }
 
   // During LOADING from error callback
-  transaction = db.transaction("foo", READ_WRITE);
+  transaction = db.transaction("foo", "readwrite");
   transaction.objectStore("foo").add({}, 1).onerror = function(event) {
     event.preventDefault();
 
     transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
     expectedAbortEventCount++
 
-    is(transaction.readyState, LOADING, "in LOADING state");
     transaction.abort();
-    is(transaction.readyState, DONE, "in DONE state after abort()");
     continueToNextStep();
   }
   yield;
 
   // In between callbacks
   transaction = db.transaction("foo");
   function makeNewRequest() {
     let r = transaction.objectStore("foo").get(1);
     r.onsuccess = makeNewRequest;
     r.onerror = abortErrorHandler;
   }
   makeNewRequest();
   transaction.objectStore("foo").get(1).onsuccess = function(event) {
     executeSoon(function() {
-      is(transaction.readyState, LOADING, "in LOADING state");
       transaction.abort();
       expectedAbortEventCount++;
-      is(transaction.readyState, DONE, "in DONE state after abort()");
       continueToNextStep();
     });
   };
   yield;
   
   // During COMMITTING
-  transaction = db.transaction("foo", READ_WRITE);
+  transaction = db.transaction("foo", "readwrite");
   transaction.objectStore("foo").put({hello: "world"}, 1).onsuccess = function(event) {
     continueToNextStep();
   };
   yield;
-  is(transaction.readyState, COMMITTING, "in COMMITTING state");
   try {
     transaction.abort();
     ok(false, "second abort should throw an error");
   }
   catch (ex) {
     ok(true, "second abort should throw an error");
   }
   transaction.oncomplete = grabEventAndContinueHandler;
   event = yield;
-  is(transaction.readyState, DONE, "in DONE state");
 
   // Since the previous transaction shouldn't have caused any error events,
   // we know that all events should have fired by now.
   is(abortEventCount, expectedAbortEventCount,
      "All abort errors fired");
 
   // Abort both failing and succeeding requests
-  transaction = db.transaction("foo", READ_WRITE);
+  transaction = db.transaction("foo", "readwrite");
   transaction.onabort = transaction.oncomplete = grabEventAndContinueHandler;
   transaction.objectStore("foo").add({indexKey: "key"}).onsuccess = function(event) {
     transaction.abort();
   };
   let request1 = transaction.objectStore("foo").add({indexKey: "key"});
   request1.onsuccess = grabEventAndContinueHandler;
   request1.onerror = grabEventAndContinueHandler;
   let request2 = transaction.objectStore("foo").get(1);
--- a/dom/indexedDB/test/unit/test_transaction_lifetimes_nested.js
+++ b/dom/indexedDB/test/unit/test_transaction_lifetimes_nested.js
@@ -15,49 +15,37 @@ function testSteps()
   let db = event.target.result;
   db.onerror = errorHandler;
 
   event.target.onsuccess = continueToNextStep;
   db.createObjectStore("foo");
   yield;
 
   let transaction1 = db.transaction("foo");
-  is(transaction1.readyState, IDBTransaction.INITIAL, "Correct readyState");
 
   let transaction2;
 
   if (this.window)
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   let thread = Components.classes["@mozilla.org/thread-manager;1"]
                          .getService()
                          .currentThread;
 
   let eventHasRun;
 
   thread.dispatch(function() {
     eventHasRun = true;
 
-    is(transaction1.readyState, IDBTransaction.INITIAL,
-       "Correct readyState");
-
     transaction2 = db.transaction("foo");
-    is(transaction2.readyState, IDBTransaction.INITIAL,
-       "Correct readyState");
-
   }, Components.interfaces.nsIThread.DISPATCH_NORMAL);
 
   while (!eventHasRun) {
     thread.processNextEvent(false);
   }
 
-  is(transaction1.readyState, IDBTransaction.INITIAL, "Correct readyState");
-
   ok(transaction2, "Non-null transaction2");
-  is(transaction2.readyState, IDBTransaction.DONE, "Correct readyState");
 
   continueToNextStep();
   yield;
 
-  is(transaction1.readyState, IDBTransaction.DONE, "Correct readyState");
-
   finishTest();
   yield;
 }
--- a/dom/indexedDB/test/unit/test_transaction_ordering.js
+++ b/dom/indexedDB/test/unit/test_transaction_ordering.js
@@ -15,32 +15,32 @@ function testSteps()
   let db = event.target.result;
   db.onerror = errorHandler;
 
   request.onsuccess = continueToNextStep;
 
   db.createObjectStore("foo");
   yield;
 
-  let trans1 = db.transaction("foo", IDBTransaction.READ_WRITE);
-  let trans2 = db.transaction("foo", IDBTransaction.READ_WRITE);
+  let trans1 = db.transaction("foo", "readwrite");
+  let trans2 = db.transaction("foo", "readwrite");
 
   let request1 = trans2.objectStore("foo").put("2", 42);
   let request2 = trans1.objectStore("foo").put("1", 42);
 
   request1.onerror = errorHandler;
   request2.onerror = errorHandler;
 
   trans1.oncomplete = grabEventAndContinueHandler;
   trans2.oncomplete = grabEventAndContinueHandler;
 
   yield;
   yield;
 
-  let trans3 = db.transaction("foo", IDBTransaction.READ);
+  let trans3 = db.transaction("foo", "readonly");
   let request = trans3.objectStore("foo").get(42);
   request.onsuccess = grabEventAndContinueHandler;
   request.onerror = errorHandler;
 
   let event = yield;
   is(event.target.result, "2", "Transactions were ordered properly.");
 
   finishTest();
--- a/dom/indexedDB/test/unit/test_writer_starvation.js
+++ b/dom/indexedDB/test/unit/test_writer_starvation.js
@@ -2,33 +2,28 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
-  const READ_ONLY = Components.interfaces.nsIIDBTransaction.READ_ONLY;
-  const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
-  const VERSION_CHANGE =
-    Components.interfaces.nsIIDBTransaction.VERSION_CHANGE;
-
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
 
   let request = mozIndexedDB.open(name, 1, description);
   request.onerror = errorHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   request.onsuccess = grabEventAndContinueHandler;
   let event = yield;
 
   let db = event.target.result;
 
-  is(event.target.transaction.mode, VERSION_CHANGE, "Correct mode");
+  is(event.target.transaction.mode, "versionchange", "Correct mode");
 
   let objectStore = db.createObjectStore("foo", { autoIncrement: true });
 
   request = objectStore.add({});
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
@@ -53,20 +48,20 @@ function testSteps()
     };
   }
 
   while (continueReading) {
     readerCount++;
     request = db.transaction("foo").objectStore("foo").get(key);
     request.onerror = errorHandler;
     request.onsuccess = function(event) {
-      is(event.target.transaction.mode, READ_ONLY, "Correct mode");
+      is(event.target.transaction.mode, "readonly", "Correct mode");
       callbackCount++;
       if (callbackCount == 100) {
-        request = db.transaction("foo", READ_WRITE)
+        request = db.transaction("foo", "readwrite")
                     .objectStore("foo")
                     .add({}, readerCount);
         request.onerror = errorHandler;
         request.onsuccess = function(event) {
           continueReading = false;
           finalCallbackCount = callbackCount;
           is(event.target.result, callbackCount,
              "write callback came before later reads");