LCOV - code coverage report
Current view: top level - dom/indexedDB - IDBCursor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 446 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 35 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "IDBCursor.h"
       8             : 
       9             : #include "IDBDatabase.h"
      10             : #include "IDBIndex.h"
      11             : #include "IDBObjectStore.h"
      12             : #include "IDBRequest.h"
      13             : #include "IDBTransaction.h"
      14             : #include "IndexedDatabaseInlines.h"
      15             : #include "mozilla/ErrorResult.h"
      16             : #include "mozilla/dom/UnionTypes.h"
      17             : #include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
      18             : #include "nsString.h"
      19             : #include "ProfilerHelpers.h"
      20             : #include "ReportInternalError.h"
      21             : 
      22             : // Include this last to avoid path problems on Windows.
      23             : #include "ActorsChild.h"
      24             : 
      25             : namespace mozilla {
      26             : namespace dom {
      27             : 
      28             : using namespace indexedDB;
      29             : 
      30           0 : IDBCursor::IDBCursor(Type aType,
      31             :                      BackgroundCursorChild* aBackgroundActor,
      32           0 :                      const Key& aKey)
      33             :   : mBackgroundActor(aBackgroundActor)
      34             :   , mRequest(aBackgroundActor->GetRequest())
      35             :   , mSourceObjectStore(aBackgroundActor->GetObjectStore())
      36             :   , mSourceIndex(aBackgroundActor->GetIndex())
      37           0 :   , mTransaction(mRequest->GetTransaction())
      38           0 :   , mScriptOwner(mTransaction->Database()->GetScriptOwner())
      39           0 :   , mCachedKey(JS::UndefinedValue())
      40           0 :   , mCachedPrimaryKey(JS::UndefinedValue())
      41           0 :   , mCachedValue(JS::UndefinedValue())
      42             :   , mKey(aKey)
      43             :   , mType(aType)
      44           0 :   , mDirection(aBackgroundActor->GetDirection())
      45             :   , mHaveCachedKey(false)
      46             :   , mHaveCachedPrimaryKey(false)
      47             :   , mHaveCachedValue(false)
      48             :   , mRooted(false)
      49             :   , mContinueCalled(false)
      50           0 :   , mHaveValue(true)
      51             : {
      52           0 :   MOZ_ASSERT(aBackgroundActor);
      53           0 :   aBackgroundActor->AssertIsOnOwningThread();
      54           0 :   MOZ_ASSERT(mRequest);
      55           0 :   MOZ_ASSERT_IF(aType == Type_ObjectStore || aType == Type_ObjectStoreKey,
      56             :                 mSourceObjectStore);
      57           0 :   MOZ_ASSERT_IF(aType == Type_Index || aType == Type_IndexKey, mSourceIndex);
      58           0 :   MOZ_ASSERT(mTransaction);
      59           0 :   MOZ_ASSERT(!aKey.IsUnset());
      60           0 :   MOZ_ASSERT(mScriptOwner);
      61             : 
      62           0 :   if (mScriptOwner) {
      63           0 :     mozilla::HoldJSObjects(this);
      64           0 :     mRooted = true;
      65             :   }
      66           0 : }
      67             : 
      68             : #ifdef ENABLE_INTL_API
      69             : bool
      70           0 : IDBCursor::IsLocaleAware() const
      71             : {
      72           0 :   return mSourceIndex && !mSourceIndex->Locale().IsEmpty();
      73             : }
      74             : #endif
      75             : 
      76           0 : IDBCursor::~IDBCursor()
      77             : {
      78           0 :   AssertIsOnOwningThread();
      79             : 
      80           0 :   DropJSObjects();
      81             : 
      82           0 :   if (mBackgroundActor) {
      83           0 :     mBackgroundActor->SendDeleteMeInternal();
      84           0 :     MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
      85             :   }
      86           0 : }
      87             : 
      88             : // static
      89             : already_AddRefed<IDBCursor>
      90           0 : IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
      91             :                   const Key& aKey,
      92             :                   StructuredCloneReadInfo&& aCloneInfo)
      93             : {
      94           0 :   MOZ_ASSERT(aBackgroundActor);
      95           0 :   aBackgroundActor->AssertIsOnOwningThread();
      96           0 :   MOZ_ASSERT(aBackgroundActor->GetObjectStore());
      97           0 :   MOZ_ASSERT(!aBackgroundActor->GetIndex());
      98           0 :   MOZ_ASSERT(!aKey.IsUnset());
      99             : 
     100             :   RefPtr<IDBCursor> cursor =
     101           0 :     new IDBCursor(Type_ObjectStore, aBackgroundActor, aKey);
     102             : 
     103           0 :   cursor->mCloneInfo = Move(aCloneInfo);
     104             : 
     105           0 :   return cursor.forget();
     106             : }
     107             : 
     108             : // static
     109             : already_AddRefed<IDBCursor>
     110           0 : IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
     111             :                   const Key& aKey)
     112             : {
     113           0 :   MOZ_ASSERT(aBackgroundActor);
     114           0 :   aBackgroundActor->AssertIsOnOwningThread();
     115           0 :   MOZ_ASSERT(aBackgroundActor->GetObjectStore());
     116           0 :   MOZ_ASSERT(!aBackgroundActor->GetIndex());
     117           0 :   MOZ_ASSERT(!aKey.IsUnset());
     118             : 
     119             :   RefPtr<IDBCursor> cursor =
     120           0 :     new IDBCursor(Type_ObjectStoreKey, aBackgroundActor, aKey);
     121             : 
     122           0 :   return cursor.forget();
     123             : }
     124             : 
     125             : // static
     126             : already_AddRefed<IDBCursor>
     127           0 : IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
     128             :                   const Key& aKey,
     129             :                   const Key& aSortKey,
     130             :                   const Key& aPrimaryKey,
     131             :                   StructuredCloneReadInfo&& aCloneInfo)
     132             : {
     133           0 :   MOZ_ASSERT(aBackgroundActor);
     134           0 :   aBackgroundActor->AssertIsOnOwningThread();
     135           0 :   MOZ_ASSERT(aBackgroundActor->GetIndex());
     136           0 :   MOZ_ASSERT(!aBackgroundActor->GetObjectStore());
     137           0 :   MOZ_ASSERT(!aKey.IsUnset());
     138           0 :   MOZ_ASSERT(!aPrimaryKey.IsUnset());
     139             : 
     140             :   RefPtr<IDBCursor> cursor =
     141           0 :     new IDBCursor(Type_Index, aBackgroundActor, aKey);
     142             : 
     143           0 :   cursor->mSortKey = Move(aSortKey);
     144           0 :   cursor->mPrimaryKey = Move(aPrimaryKey);
     145           0 :   cursor->mCloneInfo = Move(aCloneInfo);
     146             : 
     147           0 :   return cursor.forget();
     148             : }
     149             : 
     150             : // static
     151             : already_AddRefed<IDBCursor>
     152           0 : IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
     153             :                   const Key& aKey,
     154             :                   const Key& aSortKey,
     155             :                   const Key& aPrimaryKey)
     156             : {
     157           0 :   MOZ_ASSERT(aBackgroundActor);
     158           0 :   aBackgroundActor->AssertIsOnOwningThread();
     159           0 :   MOZ_ASSERT(aBackgroundActor->GetIndex());
     160           0 :   MOZ_ASSERT(!aBackgroundActor->GetObjectStore());
     161           0 :   MOZ_ASSERT(!aKey.IsUnset());
     162           0 :   MOZ_ASSERT(!aPrimaryKey.IsUnset());
     163             : 
     164             :   RefPtr<IDBCursor> cursor =
     165           0 :     new IDBCursor(Type_IndexKey, aBackgroundActor, aKey);
     166             : 
     167           0 :   cursor->mSortKey = Move(aSortKey);
     168           0 :   cursor->mPrimaryKey = Move(aPrimaryKey);
     169             : 
     170           0 :   return cursor.forget();
     171             : }
     172             : 
     173             : // static
     174             : auto
     175           0 : IDBCursor::ConvertDirection(IDBCursorDirection aDirection) -> Direction
     176             : {
     177           0 :   switch (aDirection) {
     178             :     case mozilla::dom::IDBCursorDirection::Next:
     179           0 :       return NEXT;
     180             : 
     181             :     case mozilla::dom::IDBCursorDirection::Nextunique:
     182           0 :       return NEXT_UNIQUE;
     183             : 
     184             :     case mozilla::dom::IDBCursorDirection::Prev:
     185           0 :       return PREV;
     186             : 
     187             :     case mozilla::dom::IDBCursorDirection::Prevunique:
     188           0 :       return PREV_UNIQUE;
     189             : 
     190             :     default:
     191           0 :       MOZ_CRASH("Unknown direction!");
     192             :   }
     193             : }
     194             : 
     195             : #ifdef DEBUG
     196             : 
     197             : void
     198           0 : IDBCursor::AssertIsOnOwningThread() const
     199             : {
     200           0 :   MOZ_ASSERT(mTransaction);
     201           0 :   mTransaction->AssertIsOnOwningThread();
     202           0 : }
     203             : 
     204             : #endif // DEBUG
     205             : 
     206             : void
     207           0 : IDBCursor::DropJSObjects()
     208             : {
     209           0 :   AssertIsOnOwningThread();
     210             : 
     211           0 :   Reset();
     212             : 
     213           0 :   if (!mRooted) {
     214           0 :     return;
     215             :   }
     216             : 
     217           0 :   mScriptOwner = nullptr;
     218           0 :   mRooted = false;
     219             : 
     220           0 :   mozilla::DropJSObjects(this);
     221             : }
     222             : 
     223             : bool
     224           0 : IDBCursor::IsSourceDeleted() const
     225             : {
     226           0 :   AssertIsOnOwningThread();
     227           0 :   MOZ_ASSERT(mTransaction);
     228           0 :   MOZ_ASSERT(mTransaction->IsOpen());
     229             : 
     230             :   IDBObjectStore* sourceObjectStore;
     231           0 :   if (mType == Type_Index || mType == Type_IndexKey) {
     232           0 :     MOZ_ASSERT(mSourceIndex);
     233             : 
     234           0 :     if (mSourceIndex->IsDeleted()) {
     235           0 :       return true;
     236             :     }
     237             : 
     238           0 :     sourceObjectStore = mSourceIndex->ObjectStore();
     239           0 :     MOZ_ASSERT(sourceObjectStore);
     240             :   } else {
     241           0 :     MOZ_ASSERT(mSourceObjectStore);
     242           0 :     sourceObjectStore = mSourceObjectStore;
     243             :   }
     244             : 
     245           0 :   return sourceObjectStore->IsDeleted();
     246             : }
     247             : 
     248             : void
     249           0 : IDBCursor::Reset()
     250             : {
     251           0 :   AssertIsOnOwningThread();
     252             : 
     253           0 :   mCachedKey.setUndefined();
     254           0 :   mCachedPrimaryKey.setUndefined();
     255           0 :   mCachedValue.setUndefined();
     256           0 :   IDBObjectStore::ClearCloneReadInfo(mCloneInfo);
     257             : 
     258           0 :   mHaveCachedKey = false;
     259           0 :   mHaveCachedPrimaryKey = false;
     260           0 :   mHaveCachedValue = false;
     261           0 :   mHaveValue = false;
     262           0 :   mContinueCalled = false;
     263           0 : }
     264             : 
     265             : nsPIDOMWindowInner*
     266           0 : IDBCursor::GetParentObject() const
     267             : {
     268           0 :   AssertIsOnOwningThread();
     269           0 :   MOZ_ASSERT(mTransaction);
     270             : 
     271           0 :   return mTransaction->GetParentObject();
     272             : }
     273             : 
     274             : IDBCursorDirection
     275           0 : IDBCursor::GetDirection() const
     276             : {
     277           0 :   AssertIsOnOwningThread();
     278             : 
     279           0 :   switch (mDirection) {
     280             :     case NEXT:
     281           0 :       return IDBCursorDirection::Next;
     282             : 
     283             :     case NEXT_UNIQUE:
     284           0 :       return IDBCursorDirection::Nextunique;
     285             : 
     286             :     case PREV:
     287           0 :       return IDBCursorDirection::Prev;
     288             : 
     289             :     case PREV_UNIQUE:
     290           0 :       return IDBCursorDirection::Prevunique;
     291             : 
     292             :     default:
     293           0 :       MOZ_CRASH("Bad direction!");
     294             :   }
     295             : }
     296             : 
     297             : void
     298           0 : IDBCursor::GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const
     299             : {
     300           0 :   AssertIsOnOwningThread();
     301             : 
     302           0 :   switch (mType) {
     303             :     case Type_ObjectStore:
     304             :     case Type_ObjectStoreKey:
     305           0 :       MOZ_ASSERT(mSourceObjectStore);
     306           0 :       aSource.SetAsIDBObjectStore() = mSourceObjectStore;
     307           0 :       return;
     308             : 
     309             :     case Type_Index:
     310             :     case Type_IndexKey:
     311           0 :       MOZ_ASSERT(mSourceIndex);
     312           0 :       aSource.SetAsIDBIndex() = mSourceIndex;
     313           0 :       return;
     314             : 
     315             :     default:
     316           0 :       MOZ_ASSERT_UNREACHABLE("Bad type!");
     317             :   }
     318             : }
     319             : 
     320             : void
     321           0 : IDBCursor::GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
     322             :                   ErrorResult& aRv)
     323             : {
     324           0 :   AssertIsOnOwningThread();
     325           0 :   MOZ_ASSERT(!mKey.IsUnset() || !mHaveValue);
     326             : 
     327           0 :   if (!mHaveValue) {
     328           0 :     aResult.setUndefined();
     329           0 :     return;
     330             :   }
     331             : 
     332           0 :   if (!mHaveCachedKey) {
     333           0 :     if (!mRooted) {
     334           0 :       mozilla::HoldJSObjects(this);
     335           0 :       mRooted = true;
     336             :     }
     337             : 
     338           0 :     aRv = mKey.ToJSVal(aCx, mCachedKey);
     339           0 :     if (NS_WARN_IF(aRv.Failed())) {
     340           0 :       return;
     341             :     }
     342             : 
     343           0 :     mHaveCachedKey = true;
     344             :   }
     345             : 
     346           0 :   aResult.set(mCachedKey);
     347             : }
     348             : 
     349             : void
     350           0 : IDBCursor::GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
     351             :                          ErrorResult& aRv)
     352             : {
     353           0 :   AssertIsOnOwningThread();
     354             : 
     355           0 :   if (!mHaveValue) {
     356           0 :     aResult.setUndefined();
     357           0 :     return;
     358             :   }
     359             : 
     360           0 :   if (!mHaveCachedPrimaryKey) {
     361           0 :     if (!mRooted) {
     362           0 :       mozilla::HoldJSObjects(this);
     363           0 :       mRooted = true;
     364             :     }
     365             : 
     366             :     const Key& key =
     367           0 :       (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) ?
     368             :       mKey :
     369           0 :       mPrimaryKey;
     370             : 
     371           0 :     MOZ_ASSERT(!key.IsUnset());
     372             : 
     373           0 :     aRv = key.ToJSVal(aCx, mCachedPrimaryKey);
     374           0 :     if (NS_WARN_IF(aRv.Failed())) {
     375           0 :       return;
     376             :     }
     377             : 
     378           0 :     mHaveCachedPrimaryKey = true;
     379             :   }
     380             : 
     381           0 :   aResult.set(mCachedPrimaryKey);
     382             : }
     383             : 
     384             : void
     385           0 : IDBCursor::GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
     386             :                     ErrorResult& aRv)
     387             : {
     388           0 :   AssertIsOnOwningThread();
     389           0 :   MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);
     390             : 
     391           0 :   if (!mHaveValue) {
     392           0 :     aResult.setUndefined();
     393           0 :     return;
     394             :   }
     395             : 
     396           0 :   if (!mHaveCachedValue) {
     397           0 :     if (!mRooted) {
     398           0 :       mozilla::HoldJSObjects(this);
     399           0 :       mRooted = true;
     400             :     }
     401             : 
     402           0 :     JS::Rooted<JS::Value> val(aCx);
     403           0 :     if (NS_WARN_IF(!IDBObjectStore::DeserializeValue(aCx, mCloneInfo, &val))) {
     404           0 :       aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     405           0 :       return;
     406             :     }
     407             : 
     408           0 :     IDBObjectStore::ClearCloneReadInfo(mCloneInfo);
     409             : 
     410           0 :     mCachedValue = val;
     411           0 :     mHaveCachedValue = true;
     412             :   }
     413             : 
     414           0 :   aResult.set(mCachedValue);
     415             : }
     416             : 
     417             : void
     418           0 : IDBCursor::Continue(JSContext* aCx,
     419             :                     JS::Handle<JS::Value> aKey,
     420             :                     ErrorResult &aRv)
     421             : {
     422           0 :   AssertIsOnOwningThread();
     423             : 
     424           0 :   if (!mTransaction->IsOpen()) {
     425           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     426           0 :     return;
     427             :   }
     428             : 
     429           0 :   if (IsSourceDeleted() || !mHaveValue || mContinueCalled) {
     430           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     431           0 :     return;
     432             :   }
     433             : 
     434           0 :   Key key;
     435           0 :   aRv = key.SetFromJSVal(aCx, aKey);
     436           0 :   if (aRv.Failed()) {
     437           0 :     return;
     438             :   }
     439             : 
     440             : #ifdef ENABLE_INTL_API
     441           0 :   if (IsLocaleAware() && !key.IsUnset()) {
     442           0 :     Key tmp;
     443           0 :     aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale());
     444           0 :     if (aRv.Failed()) {
     445           0 :       return;
     446             :     }
     447           0 :     key = tmp;
     448             :   }
     449             : 
     450           0 :   const Key& sortKey = IsLocaleAware() ? mSortKey : mKey;
     451             : #else
     452             :   const Key& sortKey = mKey;
     453             : #endif
     454             : 
     455           0 :   if (!key.IsUnset()) {
     456           0 :     switch (mDirection) {
     457             :       case NEXT:
     458             :       case NEXT_UNIQUE:
     459           0 :         if (key <= sortKey) {
     460           0 :           aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     461           0 :           return;
     462             :         }
     463           0 :         break;
     464             : 
     465             :       case PREV:
     466             :       case PREV_UNIQUE:
     467           0 :         if (key >= sortKey) {
     468           0 :           aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     469           0 :           return;
     470             :         }
     471           0 :         break;
     472             : 
     473             :       default:
     474           0 :         MOZ_CRASH("Unknown direction type!");
     475             :     }
     476             :   }
     477             : 
     478           0 :   const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
     479           0 :   mRequest->SetLoggingSerialNumber(requestSerialNumber);
     480             : 
     481           0 :   if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) {
     482           0 :     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     483             :                    "database(%s).transaction(%s).objectStore(%s)."
     484             :                    "cursor(%s).continue(%s)",
     485             :                  "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continue()",
     486             :                  IDB_LOG_ID_STRING(),
     487             :                  mTransaction->LoggingSerialNumber(),
     488             :                  requestSerialNumber,
     489             :                  IDB_LOG_STRINGIFY(mTransaction->Database()),
     490             :                  IDB_LOG_STRINGIFY(mTransaction),
     491             :                  IDB_LOG_STRINGIFY(mSourceObjectStore),
     492             :                  IDB_LOG_STRINGIFY(mDirection),
     493           0 :                  IDB_LOG_STRINGIFY(key));
     494             :   } else {
     495           0 :     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     496             :                    "database(%s).transaction(%s).objectStore(%s)."
     497             :                    "index(%s).cursor(%s).continue(%s)",
     498             :                  "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continue()",
     499             :                  IDB_LOG_ID_STRING(),
     500             :                  mTransaction->LoggingSerialNumber(),
     501             :                  requestSerialNumber,
     502             :                  IDB_LOG_STRINGIFY(mTransaction->Database()),
     503             :                  IDB_LOG_STRINGIFY(mTransaction),
     504             :                  IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
     505             :                  IDB_LOG_STRINGIFY(mSourceIndex),
     506             :                  IDB_LOG_STRINGIFY(mDirection),
     507             :                  IDB_LOG_STRINGIFY(key));
     508             :   }
     509             : 
     510           0 :   mBackgroundActor->SendContinueInternal(ContinueParams(key));
     511             : 
     512           0 :   mContinueCalled = true;
     513             : }
     514             : 
     515             : void
     516           0 : IDBCursor::ContinuePrimaryKey(JSContext* aCx,
     517             :                              JS::Handle<JS::Value> aKey,
     518             :                              JS::Handle<JS::Value> aPrimaryKey,
     519             :                              ErrorResult &aRv)
     520             : {
     521           0 :   AssertIsOnOwningThread();
     522             : 
     523           0 :   if (!mTransaction->IsOpen()) {
     524           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     525           0 :     return;
     526             :   }
     527             : 
     528           0 :   if (IsSourceDeleted()) {
     529           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     530           0 :     return;
     531             :   }
     532             : 
     533           0 :   if ((mType != Type_Index && mType != Type_IndexKey) ||
     534           0 :       (mDirection != NEXT && mDirection != PREV)) {
     535           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     536           0 :     return;
     537             :   }
     538             : 
     539           0 :   if (!mHaveValue || mContinueCalled) {
     540           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     541           0 :     return;
     542             :   }
     543             : 
     544           0 :   Key key;
     545           0 :   aRv = key.SetFromJSVal(aCx, aKey);
     546           0 :   if (aRv.Failed()) {
     547           0 :     return;
     548             :   }
     549             : 
     550             : #ifdef ENABLE_INTL_API
     551           0 :   if (IsLocaleAware() && !key.IsUnset()) {
     552           0 :     Key tmp;
     553           0 :     aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale());
     554           0 :     if (aRv.Failed()) {
     555           0 :       return;
     556             :     }
     557           0 :     key = tmp;
     558             :   }
     559             : 
     560           0 :   const Key& sortKey = IsLocaleAware() ? mSortKey : mKey;
     561             : #else
     562             :   const Key& sortKey = mKey;
     563             : #endif
     564             : 
     565           0 :   if (key.IsUnset()) {
     566           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     567           0 :     return;
     568             :   }
     569             : 
     570           0 :   Key primaryKey;
     571           0 :   aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey);
     572           0 :   if (aRv.Failed()) {
     573           0 :     return;
     574             :   }
     575             : 
     576           0 :   if (primaryKey.IsUnset()) {
     577           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     578           0 :     return;
     579             :   }
     580             : 
     581           0 :   switch (mDirection) {
     582             :     case NEXT:
     583           0 :       if (key < sortKey ||
     584           0 :           (key == sortKey && primaryKey <= mPrimaryKey)) {
     585           0 :         aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     586           0 :         return;
     587             :       }
     588           0 :       break;
     589             : 
     590             :     case PREV:
     591           0 :       if (key > sortKey ||
     592           0 :           (key == sortKey && primaryKey >= mPrimaryKey)) {
     593           0 :         aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     594           0 :         return;
     595             :       }
     596           0 :       break;
     597             : 
     598             :     default:
     599           0 :       MOZ_CRASH("Unknown direction type!");
     600             :   }
     601             : 
     602           0 :   const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
     603           0 :   mRequest->SetLoggingSerialNumber(requestSerialNumber);
     604             : 
     605           0 :   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     606             :                  "database(%s).transaction(%s).objectStore(%s)."
     607             :                  "index(%s).cursor(%s).continuePrimaryKey(%s, %s)",
     608             :                "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continuePrimaryKey()",
     609             :                IDB_LOG_ID_STRING(),
     610             :                mTransaction->LoggingSerialNumber(),
     611             :                requestSerialNumber,
     612             :                IDB_LOG_STRINGIFY(mTransaction->Database()),
     613             :                IDB_LOG_STRINGIFY(mTransaction),
     614             :                IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
     615             :                IDB_LOG_STRINGIFY(mSourceIndex),
     616             :                IDB_LOG_STRINGIFY(mDirection),
     617             :                IDB_LOG_STRINGIFY(key),
     618             :                IDB_LOG_STRINGIFY(primaryKey));
     619             : 
     620           0 :   mBackgroundActor->SendContinueInternal(ContinuePrimaryKeyParams(key, primaryKey));
     621             : 
     622           0 :   mContinueCalled = true;
     623             : }
     624             : 
     625             : void
     626           0 : IDBCursor::Advance(uint32_t aCount, ErrorResult &aRv)
     627             : {
     628           0 :   AssertIsOnOwningThread();
     629             : 
     630           0 :   if (!aCount) {
     631           0 :     aRv.ThrowTypeError<MSG_INVALID_ADVANCE_COUNT>();
     632           0 :     return;
     633             :   }
     634             : 
     635           0 :   if (!mTransaction->IsOpen()) {
     636           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     637           0 :     return;
     638             :   }
     639             : 
     640             : 
     641           0 :   if (IsSourceDeleted() || !mHaveValue || mContinueCalled) {
     642           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     643           0 :     return;
     644             :   }
     645             : 
     646           0 :   const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
     647           0 :   mRequest->SetLoggingSerialNumber(requestSerialNumber);
     648             : 
     649           0 :   if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) {
     650           0 :     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     651             :                    "database(%s).transaction(%s).objectStore(%s)."
     652             :                    "cursor(%s).advance(%ld)",
     653             :                  "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()",
     654             :                  IDB_LOG_ID_STRING(),
     655             :                  mTransaction->LoggingSerialNumber(),
     656             :                  requestSerialNumber,
     657             :                  IDB_LOG_STRINGIFY(mTransaction->Database()),
     658             :                  IDB_LOG_STRINGIFY(mTransaction),
     659             :                  IDB_LOG_STRINGIFY(mSourceObjectStore),
     660             :                  IDB_LOG_STRINGIFY(mDirection),
     661           0 :                  aCount);
     662             :   } else {
     663           0 :     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     664             :                    "database(%s).transaction(%s).objectStore(%s)."
     665             :                    "index(%s).cursor(%s).advance(%ld)",
     666             :                  "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()",
     667             :                  IDB_LOG_ID_STRING(),
     668             :                  mTransaction->LoggingSerialNumber(),
     669             :                  requestSerialNumber,
     670             :                  IDB_LOG_STRINGIFY(mTransaction->Database()),
     671             :                  IDB_LOG_STRINGIFY(mTransaction),
     672             :                  IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
     673             :                  IDB_LOG_STRINGIFY(mSourceIndex),
     674             :                  IDB_LOG_STRINGIFY(mDirection),
     675             :                  aCount);
     676             :   }
     677             : 
     678           0 :   mBackgroundActor->SendContinueInternal(AdvanceParams(aCount));
     679             : 
     680           0 :   mContinueCalled = true;
     681             : }
     682             : 
     683             : already_AddRefed<IDBRequest>
     684           0 : IDBCursor::Update(JSContext* aCx, JS::Handle<JS::Value> aValue,
     685             :                   ErrorResult& aRv)
     686             : {
     687           0 :   AssertIsOnOwningThread();
     688             : 
     689           0 :   if (!mTransaction->IsOpen()) {
     690           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     691           0 :     return nullptr;
     692             :   }
     693             : 
     694           0 :   if (!mTransaction->IsWriteAllowed()) {
     695           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     696           0 :     return nullptr;
     697             :   }
     698             : 
     699           0 :   if (mTransaction->GetMode() == IDBTransaction::CLEANUP ||
     700           0 :       IsSourceDeleted() ||
     701           0 :       !mHaveValue ||
     702           0 :       mType == Type_ObjectStoreKey ||
     703           0 :       mType == Type_IndexKey ||
     704           0 :       mContinueCalled) {
     705           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     706           0 :     return nullptr;
     707             :   }
     708             : 
     709           0 :   MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);
     710           0 :   MOZ_ASSERT(!mKey.IsUnset());
     711           0 :   MOZ_ASSERT_IF(mType == Type_Index, !mPrimaryKey.IsUnset());
     712             : 
     713             :   IDBObjectStore* objectStore;
     714           0 :   if (mType == Type_ObjectStore) {
     715           0 :     objectStore = mSourceObjectStore;
     716             :   } else {
     717           0 :     objectStore = mSourceIndex->ObjectStore();
     718             :   }
     719             : 
     720           0 :   MOZ_ASSERT(objectStore);
     721             : 
     722           0 :   const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey;
     723             : 
     724           0 :   RefPtr<IDBRequest> request;
     725             : 
     726           0 :   if (objectStore->HasValidKeyPath()) {
     727             :     // Make sure the object given has the correct keyPath value set on it.
     728           0 :     const KeyPath& keyPath = objectStore->GetKeyPath();
     729           0 :     Key key;
     730             : 
     731           0 :     aRv = keyPath.ExtractKey(aCx, aValue, key);
     732           0 :     if (aRv.Failed()) {
     733           0 :       return nullptr;
     734             :     }
     735             : 
     736           0 :     if (key != primaryKey) {
     737           0 :       aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     738           0 :       return nullptr;
     739             :     }
     740             : 
     741           0 :     request = objectStore->AddOrPut(aCx,
     742             :                                     aValue,
     743             :                                     /* aKey */ JS::UndefinedHandleValue,
     744             :                                     /* aOverwrite */ true,
     745             :                                     /* aFromCursor */ true,
     746           0 :                                     aRv);
     747           0 :     if (aRv.Failed()) {
     748           0 :       return nullptr;
     749             :     }
     750             :   }
     751             :   else {
     752           0 :     JS::Rooted<JS::Value> keyVal(aCx);
     753           0 :     aRv = primaryKey.ToJSVal(aCx, &keyVal);
     754           0 :     if (aRv.Failed()) {
     755           0 :       return nullptr;
     756             :     }
     757             : 
     758           0 :     request = objectStore->AddOrPut(aCx,
     759             :                                     aValue,
     760             :                                     keyVal,
     761             :                                     /* aOverwrite */ true,
     762             :                                     /* aFromCursor */ true,
     763           0 :                                     aRv);
     764           0 :     if (aRv.Failed()) {
     765           0 :       return nullptr;
     766             :     }
     767             :   }
     768             : 
     769           0 :   request->SetSource(this);
     770             : 
     771           0 :   if (mType == Type_ObjectStore) {
     772           0 :     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     773             :                    "database(%s).transaction(%s).objectStore(%s)."
     774             :                    "cursor(%s).update(%s)",
     775             :                  "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()",
     776             :                  IDB_LOG_ID_STRING(),
     777             :                  mTransaction->LoggingSerialNumber(),
     778             :                  request->LoggingSerialNumber(),
     779             :                  IDB_LOG_STRINGIFY(mTransaction->Database()),
     780             :                  IDB_LOG_STRINGIFY(mTransaction),
     781             :                  IDB_LOG_STRINGIFY(objectStore),
     782             :                  IDB_LOG_STRINGIFY(mDirection),
     783             :                  IDB_LOG_STRINGIFY(objectStore, primaryKey));
     784             :   } else {
     785           0 :     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     786             :                    "database(%s).transaction(%s).objectStore(%s)."
     787             :                    "index(%s).cursor(%s).update(%s)",
     788             :                  "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()",
     789             :                  IDB_LOG_ID_STRING(),
     790             :                  mTransaction->LoggingSerialNumber(),
     791             :                  request->LoggingSerialNumber(),
     792             :                  IDB_LOG_STRINGIFY(mTransaction->Database()),
     793             :                  IDB_LOG_STRINGIFY(mTransaction),
     794             :                  IDB_LOG_STRINGIFY(objectStore),
     795             :                  IDB_LOG_STRINGIFY(mSourceIndex),
     796             :                  IDB_LOG_STRINGIFY(mDirection),
     797             :                  IDB_LOG_STRINGIFY(objectStore, primaryKey));
     798             :   }
     799             : 
     800           0 :   return request.forget();
     801             : }
     802             : 
     803             : already_AddRefed<IDBRequest>
     804           0 : IDBCursor::Delete(JSContext* aCx, ErrorResult& aRv)
     805             : {
     806           0 :   AssertIsOnOwningThread();
     807             : 
     808           0 :   if (!mTransaction->IsOpen()) {
     809           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     810           0 :     return nullptr;
     811             :   }
     812             : 
     813           0 :   if (!mTransaction->IsWriteAllowed()) {
     814           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     815           0 :     return nullptr;
     816             :   }
     817             : 
     818           0 :   if (IsSourceDeleted() ||
     819           0 :       !mHaveValue ||
     820           0 :       mType == Type_ObjectStoreKey ||
     821           0 :       mType == Type_IndexKey ||
     822           0 :       mContinueCalled) {
     823           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     824           0 :     return nullptr;
     825             :   }
     826             : 
     827           0 :   MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);
     828           0 :   MOZ_ASSERT(!mKey.IsUnset());
     829             : 
     830             :   IDBObjectStore* objectStore;
     831           0 :   if (mType == Type_ObjectStore) {
     832           0 :     objectStore = mSourceObjectStore;
     833             :   } else {
     834           0 :     objectStore = mSourceIndex->ObjectStore();
     835             :   }
     836             : 
     837           0 :   MOZ_ASSERT(objectStore);
     838             : 
     839           0 :   const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey;
     840             : 
     841           0 :   JS::Rooted<JS::Value> key(aCx);
     842           0 :   aRv = primaryKey.ToJSVal(aCx, &key);
     843           0 :   if (NS_WARN_IF(aRv.Failed())) {
     844           0 :     return nullptr;
     845             :   }
     846             : 
     847             :   RefPtr<IDBRequest> request =
     848           0 :     objectStore->DeleteInternal(aCx, key, /* aFromCursor */ true, aRv);
     849           0 :   if (aRv.Failed()) {
     850           0 :     return nullptr;
     851             :   }
     852             : 
     853           0 :   request->SetSource(this);
     854             : 
     855           0 :   if (mType == Type_ObjectStore) {
     856           0 :   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     857             :                  "database(%s).transaction(%s).objectStore(%s)."
     858             :                  "cursor(%s).delete(%s)",
     859             :                "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()",
     860             :                IDB_LOG_ID_STRING(),
     861             :                mTransaction->LoggingSerialNumber(),
     862             :                request->LoggingSerialNumber(),
     863             :                IDB_LOG_STRINGIFY(mTransaction->Database()),
     864             :                IDB_LOG_STRINGIFY(mTransaction),
     865             :                IDB_LOG_STRINGIFY(objectStore),
     866             :                IDB_LOG_STRINGIFY(mDirection),
     867             :                IDB_LOG_STRINGIFY(objectStore, primaryKey));
     868             :   } else {
     869           0 :     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     870             :                    "database(%s).transaction(%s).objectStore(%s)."
     871             :                    "index(%s).cursor(%s).delete(%s)",
     872             :                  "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()",
     873             :                  IDB_LOG_ID_STRING(),
     874             :                  mTransaction->LoggingSerialNumber(),
     875             :                  request->LoggingSerialNumber(),
     876             :                  IDB_LOG_STRINGIFY(mTransaction->Database()),
     877             :                  IDB_LOG_STRINGIFY(mTransaction),
     878             :                  IDB_LOG_STRINGIFY(objectStore),
     879             :                  IDB_LOG_STRINGIFY(mSourceIndex),
     880             :                  IDB_LOG_STRINGIFY(mDirection),
     881             :                  IDB_LOG_STRINGIFY(objectStore, primaryKey));
     882             :   }
     883             : 
     884           0 :   return request.forget();
     885             : }
     886             : 
     887             : void
     888           0 : IDBCursor::Reset(Key&& aKey, StructuredCloneReadInfo&& aValue)
     889             : {
     890           0 :   AssertIsOnOwningThread();
     891           0 :   MOZ_ASSERT(mType == Type_ObjectStore);
     892             : 
     893           0 :   Reset();
     894             : 
     895           0 :   mKey = Move(aKey);
     896           0 :   mCloneInfo = Move(aValue);
     897             : 
     898           0 :   mHaveValue = !mKey.IsUnset();
     899           0 : }
     900             : 
     901             : void
     902           0 : IDBCursor::Reset(Key&& aKey)
     903             : {
     904           0 :   AssertIsOnOwningThread();
     905           0 :   MOZ_ASSERT(mType == Type_ObjectStoreKey);
     906             : 
     907           0 :   Reset();
     908             : 
     909           0 :   mKey = Move(aKey);
     910             : 
     911           0 :   mHaveValue = !mKey.IsUnset();
     912           0 : }
     913             : 
     914             : void
     915           0 : IDBCursor::Reset(Key&& aKey,
     916             :                  Key&& aSortKey,
     917             :                  Key&& aPrimaryKey,
     918             :                  StructuredCloneReadInfo&& aValue)
     919             : {
     920           0 :   AssertIsOnOwningThread();
     921           0 :   MOZ_ASSERT(mType == Type_Index);
     922             : 
     923           0 :   Reset();
     924             : 
     925           0 :   mKey = Move(aKey);
     926           0 :   mSortKey = Move(aSortKey);
     927           0 :   mPrimaryKey = Move(aPrimaryKey);
     928           0 :   mCloneInfo = Move(aValue);
     929             : 
     930           0 :   mHaveValue = !mKey.IsUnset();
     931           0 : }
     932             : 
     933             : void
     934           0 : IDBCursor::Reset(Key&& aKey,
     935             :                  Key&& aSortKey,
     936             :                  Key&& aPrimaryKey)
     937             : {
     938           0 :   AssertIsOnOwningThread();
     939           0 :   MOZ_ASSERT(mType == Type_IndexKey);
     940             : 
     941           0 :   Reset();
     942             : 
     943           0 :   mKey = Move(aKey);
     944           0 :   mSortKey = Move(aSortKey);
     945           0 :   mPrimaryKey = Move(aPrimaryKey);
     946             : 
     947           0 :   mHaveValue = !mKey.IsUnset();
     948           0 : }
     949             : 
     950           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBCursor)
     951           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBCursor)
     952             : 
     953           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBCursor)
     954           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     955           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     956           0 : NS_INTERFACE_MAP_END
     957             : 
     958             : NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor)
     959             : 
     960           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
     961           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
     962           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceObjectStore)
     963           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceIndex)
     964           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     965             : 
     966           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
     967           0 :   MOZ_ASSERT_IF(!tmp->mHaveCachedKey, tmp->mCachedKey.isUndefined());
     968           0 :   MOZ_ASSERT_IF(!tmp->mHaveCachedPrimaryKey,
     969             :                 tmp->mCachedPrimaryKey.isUndefined());
     970           0 :   MOZ_ASSERT_IF(!tmp->mHaveCachedValue, tmp->mCachedValue.isUndefined());
     971             : 
     972           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
     973           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScriptOwner)
     974           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedKey)
     975           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedPrimaryKey)
     976           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedValue)
     977           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
     978             : 
     979           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
     980             :   // Don't unlink mRequest, mSourceObjectStore, or mSourceIndex!
     981           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     982           0 :   tmp->DropJSObjects();
     983           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     984             : 
     985             : JSObject*
     986           0 : IDBCursor::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     987             : {
     988           0 :   AssertIsOnOwningThread();
     989             : 
     990           0 :   switch (mType) {
     991             :     case Type_ObjectStore:
     992             :     case Type_Index:
     993           0 :       return IDBCursorWithValueBinding::Wrap(aCx, this, aGivenProto);
     994             : 
     995             :     case Type_ObjectStoreKey:
     996             :     case Type_IndexKey:
     997           0 :       return IDBCursorBinding::Wrap(aCx, this, aGivenProto);
     998             : 
     999             :     default:
    1000           0 :       MOZ_CRASH("Bad type!");
    1001             :   }
    1002             : }
    1003             : 
    1004             : } // namespace dom
    1005             : } // namespace mozilla

Generated by: LCOV version 1.13