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 91696 5a7686f1119b038eddbff7d49a169ef1c78f5391
parent 91695 825a808d224f2c7fc5115ce4686a08e1535a230e
child 91697 4d64d2d31843f0f9b7b2385c6b100eb6a636e18b
push id783
push userlsblakk@mozilla.com
push dateTue, 24 Apr 2012 17:33:42 +0000
treeherdermozilla-beta@11faed19f136 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs735094
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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");