LCOV - app.info - dom/indexedDB/IDBCursor.cpp

LCOV - code coverage report
| Current view: | directory - dom/indexedDB - IDBCursor.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 405 | 352 | 86.9 %
| Date: | 2012-07-07 | Functions: | 46 | 42 | 91.3 %

           1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* vim: set ts=2 et sw=2 tw=80: */
           3                 : /* ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Indexed Database.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * The Mozilla Foundation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 2010
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Ben Turner <bent.mozilla@gmail.com>
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #include "IDBCursor.h"
          41                 :
          42                 : #include "mozilla/storage.h"
          43                 : #include "nsComponentManagerUtils.h"
          44                 : #include "nsContentUtils.h"
          45                 : #include "nsDOMClassInfoID.h"
          46                 : #include "nsEventDispatcher.h"
          47                 : #include "nsJSUtils.h"
          48                 : #include "nsThreadUtils.h"
          49                 :
          50                 : #include "AsyncConnectionHelper.h"
          51                 : #include "IDBEvents.h"
          52                 : #include "IDBIndex.h"
          53                 : #include "IDBObjectStore.h"
          54                 : #include "IDBTransaction.h"
          55                 : #include "TransactionThreadPool.h"
          56                 :
          57                 : USING_INDEXEDDB_NAMESPACE
          58                 :
          59                 : namespace {
          60                 :
          61                 : inline
          62                 : already_AddRefed<IDBRequest>
          63                 : GenerateRequest(IDBCursor* aCursor)
          64                 : {
          65                 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
          66                 :   IDBDatabase* database = aCursor->Transaction()->Database();
          67                 :   return IDBRequest::Create(aCursor, database, aCursor->Transaction());
          68                 : }
          69                 :
          70                 : } // anonymous namespace
          71                 :
          72                 : BEGIN_INDEXEDDB_NAMESPACE
          73                 :
          74                 : class ContinueHelper : public AsyncConnectionHelper
          75                 : {
          76                 : public:
          77            1778 :   ContinueHelper(IDBCursor* aCursor,
          78                 :                  PRInt32 aCount)
          79                 :   : AsyncConnectionHelper(aCursor->mTransaction, aCursor->mRequest),
          80            1778 :     mCursor(aCursor), mCount(aCount)
          81                 :   {
          82            1778 :     NS_ASSERTION(aCount > 0, "Must have a count!");
          83            1778 :   }
          84                 :
          85            1778 :   ~ContinueHelper()
          86            3556 :   {
          87            1778 :     IDBObjectStore::ClearStructuredCloneBuffer(mCloneReadInfo.mCloneBuffer);
          88            3556 :   }
          89                 :
          90                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
          91                 :   nsresult GetSuccessResult(JSContext* aCx,
          92                 :                             jsval* aVal);
          93                 :
          94            1778 :   void ReleaseMainThreadObjects()
          95                 :   {
          96            1778 :     mCursor = nsnull;
          97            1778 :     AsyncConnectionHelper::ReleaseMainThreadObjects();
          98            1778 :   }
          99                 :
         100                 : protected:
         101                 :   virtual nsresult
         102                 :   BindArgumentsToStatement(mozIStorageStatement* aStatement) = 0;
         103                 :
         104                 :   virtual nsresult
         105                 :   GatherResultsFromStatement(mozIStorageStatement* aStatement) = 0;
         106                 :
         107                 : protected:
         108                 :   nsRefPtr<IDBCursor> mCursor;
         109                 :   PRInt32 mCount;
         110                 :   Key mKey;
         111                 :   Key mObjectKey;
         112                 :   StructuredCloneReadInfo mCloneReadInfo;
         113                 : };
         114                 :
         115                 : class ContinueObjectStoreHelper : public ContinueHelper
         116            5292 : {
         117                 : public:
         118            1323 :   ContinueObjectStoreHelper(IDBCursor* aCursor,
         119                 :                             PRUint32 aCount)
         120            1323 :   : ContinueHelper(aCursor, aCount)
         121            1323 :   { }
         122                 :
         123                 : private:
         124                 :   nsresult BindArgumentsToStatement(mozIStorageStatement* aStatement);
         125                 :   nsresult GatherResultsFromStatement(mozIStorageStatement* aStatement);
         126                 : };
         127                 :
         128                 : class ContinueIndexHelper : public ContinueHelper
         129            1472 : {
         130                 : public:
         131             455 :   ContinueIndexHelper(IDBCursor* aCursor,
         132                 :                       PRUint32 aCount)
         133             455 :   : ContinueHelper(aCursor, aCount)
         134             455 :   { }
         135                 :
         136                 : private:
         137                 :   nsresult BindArgumentsToStatement(mozIStorageStatement* aStatement);
         138                 :   nsresult GatherResultsFromStatement(mozIStorageStatement* aStatement);
         139                 : };
         140                 :
         141                 : class ContinueIndexObjectHelper : public ContinueIndexHelper
         142             696 : {
         143                 : public:
         144             174 :   ContinueIndexObjectHelper(IDBCursor* aCursor,
         145                 :                             PRUint32 aCount)
         146             174 :   : ContinueIndexHelper(aCursor, aCount)
         147             174 :   { }
         148                 :
         149                 : private:
         150                 :   nsresult GatherResultsFromStatement(mozIStorageStatement* aStatement);
         151                 : };
         152                 :
         153                 : END_INDEXEDDB_NAMESPACE
         154                 :
         155                 : // static
         156                 : already_AddRefed<IDBCursor>
         157              38 : IDBCursor::Create(IDBRequest* aRequest,
         158                 :                   IDBTransaction* aTransaction,
         159                 :                   IDBObjectStore* aObjectStore,
         160                 :                   Direction aDirection,
         161                 :                   const Key& aRangeKey,
         162                 :                   const nsACString& aContinueQuery,
         163                 :                   const nsACString& aContinueToQuery,
         164                 :                   const Key& aKey,
         165                 :                   StructuredCloneReadInfo& aCloneReadInfo)
         166                 : {
         167              38 :   NS_ASSERTION(aObjectStore, "Null pointer!");
         168              38 :   NS_ASSERTION(!aKey.IsUnset(), "Bad key!");
         169                 :
         170                 :   nsRefPtr<IDBCursor> cursor =
         171                 :     IDBCursor::CreateCommon(aRequest, aTransaction, aObjectStore, aDirection,
         172              76 :                             aRangeKey, aContinueQuery, aContinueToQuery);
         173              38 :   NS_ASSERTION(cursor, "This shouldn't fail!");
         174                 :
         175              38 :   cursor->mObjectStore = aObjectStore;
         176              38 :   cursor->mType = OBJECTSTORE;
         177              38 :   cursor->mKey = aKey;
         178              38 :   cursor->mCloneReadInfo.Swap(aCloneReadInfo);
         179                 :
         180              38 :   return cursor.forget();
         181                 : }
         182                 :
         183                 : // static
         184                 : already_AddRefed<IDBCursor>
         185              74 : IDBCursor::Create(IDBRequest* aRequest,
         186                 :                   IDBTransaction* aTransaction,
         187                 :                   IDBIndex* aIndex,
         188                 :                   Direction aDirection,
         189                 :                   const Key& aRangeKey,
         190                 :                   const nsACString& aContinueQuery,
         191                 :                   const nsACString& aContinueToQuery,
         192                 :                   const Key& aKey,
         193                 :                   const Key& aObjectKey)
         194                 : {
         195              74 :   NS_ASSERTION(aIndex, "Null pointer!");
         196              74 :   NS_ASSERTION(!aKey.IsUnset(), "Bad key!");
         197              74 :   NS_ASSERTION(!aObjectKey.IsUnset(), "Bad key!");
         198                 :
         199                 :   nsRefPtr<IDBCursor> cursor =
         200                 :     IDBCursor::CreateCommon(aRequest, aTransaction, aIndex->ObjectStore(),
         201                 :                             aDirection, aRangeKey, aContinueQuery,
         202             148 :                             aContinueToQuery);
         203              74 :   NS_ASSERTION(cursor, "This shouldn't fail!");
         204                 :
         205              74 :   cursor->mIndex = aIndex;
         206              74 :   cursor->mType = INDEXKEY;
         207              74 :   cursor->mKey = aKey,
         208              74 :   cursor->mObjectKey = aObjectKey;
         209                 :
         210              74 :   return cursor.forget();
         211                 : }
         212                 :
         213                 : // static
         214                 : already_AddRefed<IDBCursor>
         215              51 : IDBCursor::Create(IDBRequest* aRequest,
         216                 :                   IDBTransaction* aTransaction,
         217                 :                   IDBIndex* aIndex,
         218                 :                   Direction aDirection,
         219                 :                   const Key& aRangeKey,
         220                 :                   const nsACString& aContinueQuery,
         221                 :                   const nsACString& aContinueToQuery,
         222                 :                   const Key& aKey,
         223                 :                   const Key& aObjectKey,
         224                 :                   StructuredCloneReadInfo& aCloneReadInfo)
         225                 : {
         226              51 :   NS_ASSERTION(aIndex, "Null pointer!");
         227              51 :   NS_ASSERTION(!aKey.IsUnset(), "Bad key!");
         228                 :
         229                 :   nsRefPtr<IDBCursor> cursor =
         230                 :     IDBCursor::CreateCommon(aRequest, aTransaction, aIndex->ObjectStore(),
         231                 :                             aDirection, aRangeKey, aContinueQuery,
         232             102 :                             aContinueToQuery);
         233              51 :   NS_ASSERTION(cursor, "This shouldn't fail!");
         234                 :
         235              51 :   cursor->mObjectStore = aIndex->ObjectStore();
         236              51 :   cursor->mIndex = aIndex;
         237              51 :   cursor->mType = INDEXOBJECT;
         238              51 :   cursor->mKey = aKey;
         239              51 :   cursor->mObjectKey = aObjectKey;
         240              51 :   cursor->mCloneReadInfo.Swap(aCloneReadInfo);
         241                 :
         242              51 :   return cursor.forget();
         243                 : }
         244                 :
         245                 : // static
         246                 : nsresult
         247              16 : IDBCursor::ParseDirection(const nsAString& aDirection, Direction* aResult)
         248                 : {
         249              16 :   if (aDirection.EqualsLiteral("next")) {
         250               4 :     *aResult = NEXT;
         251                 :   }
         252              12 :   else if (aDirection.EqualsLiteral("nextunique")) {
         253               2 :     *aResult = NEXT_UNIQUE;
         254                 :   }
         255              10 :   else if (aDirection.EqualsLiteral("prev")) {
         256               8 :     *aResult = PREV;
         257                 :   }
         258               2 :   else if (aDirection.EqualsLiteral("prevunique")) {
         259               2 :     *aResult = PREV_UNIQUE;
         260                 :   }
         261                 :   else {
         262               0 :     return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
         263                 :   }
         264                 :
         265              16 :   return NS_OK;
         266                 : }
         267                 :
         268                 : // static
         269                 : already_AddRefed<IDBCursor>
         270             163 : IDBCursor::CreateCommon(IDBRequest* aRequest,
         271                 :                         IDBTransaction* aTransaction,
         272                 :                         IDBObjectStore* aObjectStore,
         273                 :                         Direction aDirection,
         274                 :                         const Key& aRangeKey,
         275                 :                         const nsACString& aContinueQuery,
         276                 :                         const nsACString& aContinueToQuery)
         277                 : {
         278             163 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         279             163 :   NS_ASSERTION(aRequest, "Null pointer!");
         280             163 :   NS_ASSERTION(aTransaction, "Null pointer!");
         281             163 :   NS_ASSERTION(aObjectStore, "Null pointer!");
         282             163 :   NS_ASSERTION(!aContinueQuery.IsEmpty(), "Empty query!");
         283             163 :   NS_ASSERTION(!aContinueToQuery.IsEmpty(), "Empty query!");
         284                 :
         285             326 :   nsRefPtr<IDBCursor> cursor = new IDBCursor();
         286                 :
         287             163 :   IDBDatabase* database = aTransaction->Database();
         288             163 :   cursor->mScriptOwner = database->GetScriptOwner();
         289                 :
         290             163 :   if (cursor->mScriptOwner) {
         291             163 :     if (NS_FAILED(NS_HOLD_JS_OBJECTS(cursor, IDBCursor))) {
         292               0 :       return nsnull;
         293                 :     }
         294                 :
         295             163 :     cursor->mRooted = true;
         296                 :   }
         297                 :
         298             163 :   cursor->mRequest = aRequest;
         299             163 :   cursor->mTransaction = aTransaction;
         300             163 :   cursor->mObjectStore = aObjectStore;
         301             163 :   cursor->mDirection = aDirection;
         302             163 :   cursor->mContinueQuery = aContinueQuery;
         303             163 :   cursor->mContinueToQuery = aContinueToQuery;
         304             163 :   cursor->mRangeKey = aRangeKey;
         305                 :
         306             163 :   return cursor.forget();
         307                 : }
         308                 :
         309             163 : IDBCursor::IDBCursor()
         310                 : : mScriptOwner(nsnull),
         311                 :   mType(OBJECTSTORE),
         312                 :   mDirection(IDBCursor::NEXT),
         313                 :   mCachedKey(JSVAL_VOID),
         314                 :   mCachedPrimaryKey(JSVAL_VOID),
         315                 :   mCachedValue(JSVAL_VOID),
         316                 :   mHaveCachedKey(false),
         317                 :   mHaveCachedPrimaryKey(false),
         318                 :   mHaveCachedValue(false),
         319                 :   mRooted(false),
         320                 :   mContinueCalled(false),
         321             163 :   mHaveValue(true)
         322                 : {
         323             163 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         324             163 : }
         325                 :
         326             326 : IDBCursor::~IDBCursor()
         327                 : {
         328             163 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         329                 :
         330             163 :   if (mRooted) {
         331             155 :     NS_DROP_JS_OBJECTS(this, IDBCursor);
         332                 :   }
         333             163 :   IDBObjectStore::ClearStructuredCloneBuffer(mCloneReadInfo.mCloneBuffer);
         334             163 : }
         335                 :
         336                 : nsresult
         337            1788 : IDBCursor::ContinueInternal(const Key& aKey,
         338                 :                             PRInt32 aCount)
         339                 : {
         340            1788 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         341            1788 :   NS_ASSERTION(aCount > 0, "Must have a count!");
         342                 :
         343            1788 :   if (!mTransaction->IsOpen()) {
         344               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
         345                 :   }
         346                 :
         347            1788 :   if (!mHaveValue || mContinueCalled) {
         348              10 :     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
         349                 :   }
         350                 :
         351            1778 :   mContinueToKey = aKey;
         352                 :
         353                 : #ifdef DEBUG
         354                 :   {
         355            3556 :     nsAutoString readyState;
         356            1778 :     if (NS_FAILED(mRequest->GetReadyState(readyState))) {
         357               0 :       NS_ERROR("This should never fail!");
         358                 :     }
         359            1778 :     NS_ASSERTION(readyState.EqualsLiteral("done"), "Should be DONE!");
         360                 :   }
         361                 : #endif
         362                 :
         363            1778 :   mRequest->Reset();
         364                 :
         365            3556 :   nsRefPtr<ContinueHelper> helper;
         366            1778 :   switch (mType) {
         367                 :     case OBJECTSTORE:
         368            1323 :       helper = new ContinueObjectStoreHelper(this, aCount);
         369            1323 :       break;
         370                 :
         371                 :     case INDEXKEY:
         372             281 :       helper = new ContinueIndexHelper(this, aCount);
         373             281 :       break;
         374                 :
         375                 :     case INDEXOBJECT:
         376             174 :       helper = new ContinueIndexObjectHelper(this, aCount);
         377             174 :       break;
         378                 :
         379                 :     default:
         380               0 :       NS_NOTREACHED("Unknown cursor type!");
         381                 :   }
         382                 :
         383            1778 :   nsresult rv = helper->DispatchToTransactionPool();
         384            1778 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
         385                 :
         386            1778 :   mContinueCalled = true;
         387            1778 :   return NS_OK;
         388                 : }
         389                 :
         390            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor)
         391                 :
         392               8 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
         393               8 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
         394               8 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mRequest,
         395                 :                                                        nsIDOMEventTarget)
         396               8 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTransaction,
         397                 :                                                        nsIDOMEventTarget)
         398               8 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mObjectStore)
         399               8 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mIndex)
         400               8 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
         401                 :
         402             221 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
         403             221 :   NS_ASSERTION(tmp->mHaveCachedKey || JSVAL_IS_VOID(tmp->mCachedKey),
         404                 :                "Should have a cached key");
         405             221 :   NS_ASSERTION(tmp->mHaveCachedPrimaryKey ||
         406                 :                JSVAL_IS_VOID(tmp->mCachedPrimaryKey),
         407                 :                "Should have a cached primary key");
         408             221 :   NS_ASSERTION(tmp->mHaveCachedValue || JSVAL_IS_VOID(tmp->mCachedValue),
         409                 :                "Should have a cached value");
         410             221 :   if (tmp->mScriptOwner) {
         411             221 :     NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mScriptOwner,
         412                 :                                                "mScriptOwner")
         413                 :   }
         414             221 :   if (JSVAL_IS_GCTHING(tmp->mCachedKey)) {
         415               0 :     void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedKey);
         416               0 :     NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedKey")
         417                 :   }
         418             221 :   if (JSVAL_IS_GCTHING(tmp->mCachedPrimaryKey)) {
         419               0 :     void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedPrimaryKey);
         420               0 :     NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedPrimaryKey")
         421                 :   }
         422             221 :   if (JSVAL_IS_GCTHING(tmp->mCachedValue)) {
         423              48 :     void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedValue);
         424              48 :     NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedValue")
         425                 :   }
         426             221 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
         427                 :
         428               8 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
         429                 :   // Don't unlink mObjectStore, mIndex, or mTransaction!
         430               8 :   if (tmp->mRooted) {
         431               8 :     NS_DROP_JS_OBJECTS(tmp, IDBCursor);
         432               8 :     tmp->mScriptOwner = nsnull;
         433               8 :     tmp->mCachedKey = JSVAL_VOID;
         434               8 :     tmp->mCachedPrimaryKey = JSVAL_VOID;
         435               8 :     tmp->mCachedValue = JSVAL_VOID;
         436               8 :     tmp->mHaveCachedKey = false;
         437               8 :     tmp->mHaveCachedPrimaryKey = false;
         438               8 :     tmp->mHaveCachedValue = false;
         439               8 :     tmp->mRooted = false;
         440               8 :     tmp->mHaveValue = false;
         441                 :   }
         442               8 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest)
         443               8 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
         444                 :
         445           17072 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBCursor)
         446           11184 :   NS_INTERFACE_MAP_ENTRY(nsIIDBCursor)
         447            8238 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIDBCursorWithValue, mType != INDEXKEY)
         448            7541 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(IDBCursorWithValue,
         449                 :                                                    mType != INDEXKEY)
         450            7452 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(IDBCursor,
         451                 :                                                    mType == INDEXKEY)
         452            7378 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
         453            5592 : NS_INTERFACE_MAP_END
         454                 :
         455            7378 : NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBCursor)
         456            7541 : NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBCursor)
         457                 :
         458                 : DOMCI_DATA(IDBCursor, IDBCursor)
         459                 : DOMCI_DATA(IDBCursorWithValue, IDBCursor)
         460                 :
         461                 : NS_IMETHODIMP
         462               0 : IDBCursor::GetDirection(nsAString& aDirection)
         463                 : {
         464               0 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         465                 :
         466               0 :   switch(mDirection) {
         467                 :     case NEXT:
         468               0 :       aDirection.AssignLiteral("next");
         469               0 :       break;
         470                 :     case NEXT_UNIQUE:
         471               0 :       aDirection.AssignLiteral("nextunique");
         472               0 :       break;
         473                 :     case PREV:
         474               0 :       aDirection.AssignLiteral("prev");
         475               0 :       break;
         476                 :     case PREV_UNIQUE:
         477               0 :       aDirection.AssignLiteral("prevunique");
         478                 :   }
         479                 :
         480               0 :   return NS_OK;
         481                 : }
         482                 :
         483                 : NS_IMETHODIMP
         484               0 : IDBCursor::GetSource(nsISupports** aSource)
         485                 : {
         486               0 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         487                 :
         488                 :   return mType == OBJECTSTORE ?
         489               0 :          CallQueryInterface(mObjectStore, aSource) :
         490               0 :          CallQueryInterface(mIndex, aSource);
         491                 : }
         492                 :
         493                 : NS_IMETHODIMP
         494             659 : IDBCursor::GetKey(JSContext* aCx,
         495                 :                   jsval* aKey)
         496                 : {
         497             659 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         498                 :
         499             659 :   NS_ASSERTION(!mKey.IsUnset() || !mHaveValue, "Bad key!");
         500                 :
         501             659 :   if (!mHaveValue) {
         502               0 :     *aKey = JSVAL_VOID;
         503               0 :     return NS_OK;
         504                 :   }
         505                 :
         506             659 :   if (!mHaveCachedKey) {
         507             429 :     if (!mRooted) {
         508               0 :       NS_HOLD_JS_OBJECTS(this, IDBCursor);
         509               0 :       mRooted = true;
         510                 :     }
         511                 :
         512             858 :     JSAutoRequest ar(aCx);
         513                 :
         514             429 :     nsresult rv = mKey.ToJSVal(aCx, &mCachedKey);
         515             429 :     NS_ENSURE_SUCCESS(rv, rv);
         516                 :
         517             858 :     mHaveCachedKey = true;
         518                 :   }
         519                 :
         520             659 :   *aKey = mCachedKey;
         521             659 :   return NS_OK;
         522                 : }
         523                 :
         524                 : NS_IMETHODIMP
         525             469 : IDBCursor::GetPrimaryKey(JSContext* aCx,
         526                 :                          jsval* aValue)
         527                 : {
         528             469 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         529                 :
         530             469 :   if (!mHaveValue) {
         531               0 :     *aValue = JSVAL_VOID;
         532               0 :     return NS_OK;
         533                 :   }
         534                 :
         535             469 :   if (!mHaveCachedPrimaryKey) {
         536             365 :     if (!mRooted) {
         537               0 :       NS_HOLD_JS_OBJECTS(this, IDBCursor);
         538               0 :       mRooted = true;
         539                 :     }
         540                 :
         541             730 :     JSAutoRequest ar(aCx);
         542                 :
         543             365 :     NS_ASSERTION(mType == OBJECTSTORE ? !mKey.IsUnset() :
         544                 :                                         !mObjectKey.IsUnset(), "Bad key!");
         545                 :
         546             365 :     const Key& key = mType == OBJECTSTORE ? mKey : mObjectKey;
         547                 :
         548             365 :     nsresult rv = key.ToJSVal(aCx, &mCachedPrimaryKey);
         549             365 :     NS_ENSURE_SUCCESS(rv, rv);
         550                 :
         551             730 :     mHaveCachedPrimaryKey = true;
         552                 :   }
         553                 :
         554             469 :   *aValue = mCachedPrimaryKey;
         555             469 :   return NS_OK;
         556                 : }
         557                 :
         558                 : NS_IMETHODIMP
         559             697 : IDBCursor::GetValue(JSContext* aCx,
         560                 :                     jsval* aValue)
         561                 : {
         562             697 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         563             697 :   NS_ASSERTION(mType != INDEXKEY, "GetValue shouldn't exist on index keys");
         564                 :
         565             697 :   if (!mHaveValue) {
         566               0 :     *aValue = JSVAL_VOID;
         567               0 :     return NS_OK;
         568                 :   }
         569                 :
         570             697 :   if (!mHaveCachedValue) {
         571             288 :     if (!mRooted) {
         572               0 :       NS_HOLD_JS_OBJECTS(this, IDBCursor);
         573               0 :       mRooted = true;
         574                 :     }
         575                 :
         576             288 :     if (!IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, &mCachedValue)) {
         577               0 :       mCachedValue = JSVAL_VOID;
         578               0 :       return NS_ERROR_DOM_DATA_CLONE_ERR;
         579                 :     }
         580                 :
         581             288 :     mCloneReadInfo.mCloneBuffer.clear();
         582             288 :     mHaveCachedValue = true;
         583                 :   }
         584                 :
         585             697 :   *aValue = mCachedValue;
         586             697 :   return NS_OK;
         587                 : }
         588                 :
         589                 : NS_IMETHODIMP
         590            1782 : IDBCursor::Continue(const jsval &aKey,
         591                 :                     JSContext* aCx)
         592                 : {
         593            1782 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         594                 :
         595            3564 :   Key key;
         596            1782 :   nsresult rv = key.SetFromJSVal(aCx, aKey);
         597            1782 :   NS_ENSURE_SUCCESS(rv, rv);
         598                 :
         599            1782 :   if (!key.IsUnset()) {
         600               7 :     switch (mDirection) {
         601                 :       case IDBCursor::NEXT:
         602                 :       case IDBCursor::NEXT_UNIQUE:
         603               7 :         if (key <= mKey) {
         604               0 :           return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
         605                 :         }
         606               7 :         break;
         607                 :
         608                 :       case IDBCursor::PREV:
         609                 :       case IDBCursor::PREV_UNIQUE:
         610               0 :         if (key >= mKey) {
         611               0 :           return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
         612                 :         }
         613               0 :         break;
         614                 :
         615                 :       default:
         616               0 :         NS_NOTREACHED("Unknown direction type!");
         617                 :     }
         618                 :   }
         619                 :
         620            1782 :   return ContinueInternal(key, 1);
         621                 : }
         622                 :
         623                 : NS_IMETHODIMP
         624              21 : IDBCursor::Update(const jsval& aValue,
         625                 :                   JSContext* aCx,
         626                 :                   nsIIDBRequest** _retval)
         627                 : {
         628              21 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         629                 :
         630              21 :   if (!mTransaction->IsOpen()) {
         631               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
         632                 :   }
         633                 :
         634              21 :   if (!mTransaction->IsWriteAllowed()) {
         635               0 :     return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR;
         636                 :   }
         637                 :
         638              21 :   if (!mHaveValue || mType == INDEXKEY) {
         639               0 :     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
         640                 :   }
         641                 :
         642              21 :   NS_ASSERTION(mObjectStore, "This cannot be null!");
         643              21 :   NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
         644              21 :   NS_ASSERTION(mType != INDEXOBJECT || !mObjectKey.IsUnset(), "Bad key!");
         645                 :
         646                 :   nsresult rv;
         647                 :
         648              42 :   JSAutoRequest ar(aCx);
         649                 :
         650              21 :   Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
         651                 :
         652              21 :   if (!mObjectStore->KeyPath().IsEmpty()) {
         653                 :     // This has to be an object.
         654              14 :     if (JSVAL_IS_PRIMITIVE(aValue)) {
         655               0 :       return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
         656                 :     }
         657                 :
         658                 :     // Make sure the object given has the correct keyPath value set on it.
         659              14 :     const nsString& keyPath = mObjectStore->KeyPath();
         660                 :
         661                 :     jsval prop;
         662                 :     JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(aValue),
         663              14 :                                  reinterpret_cast<const jschar*>(keyPath.get()),
         664              28 :                                  keyPath.Length(), &prop);
         665              14 :     NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
         666                 :
         667              28 :     Key key;
         668              14 :     rv = key.SetFromJSVal(aCx, prop);
         669              14 :     if (NS_FAILED(rv)) {
         670               0 :       return rv;
         671                 :     }
         672                 :
         673              14 :     if (key != objectKey) {
         674               0 :       return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
         675                 :     }
         676                 :
         677              14 :     return mObjectStore->Put(aValue, JSVAL_VOID, aCx, 0, _retval);
         678                 :   }
         679                 :
         680                 :   jsval keyVal;
         681               7 :   rv = objectKey.ToJSVal(aCx, &keyVal);
         682               7 :   NS_ENSURE_SUCCESS(rv, rv);
         683                 :
         684               7 :   return mObjectStore->Put(aValue, keyVal, aCx, 1, _retval);
         685                 : }
         686                 :
         687                 : NS_IMETHODIMP
         688               9 : IDBCursor::Delete(JSContext* aCx,
         689                 :                   nsIIDBRequest** _retval)
         690                 : {
         691               9 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         692                 :
         693               9 :   if (!mTransaction->IsOpen()) {
         694               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
         695                 :   }
         696                 :
         697               9 :   if (!mTransaction->IsWriteAllowed()) {
         698               0 :     return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR;
         699                 :   }
         700                 :
         701               9 :   if (!mHaveValue || mType == INDEXKEY) {
         702               0 :     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
         703                 :   }
         704                 :
         705               9 :   NS_ASSERTION(mObjectStore, "This cannot be null!");
         706               9 :   NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
         707                 :
         708               9 :   Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
         709                 :
         710                 :   jsval key;
         711               9 :   nsresult rv = objectKey.ToJSVal(aCx, &key);
         712               9 :   NS_ENSURE_SUCCESS(rv, rv);
         713                 :
         714               9 :   return mObjectStore->Delete(key, aCx, _retval);
         715                 : }
         716                 :
         717                 : NS_IMETHODIMP
         718               6 : IDBCursor::Advance(PRInt32 aCount)
         719                 : {
         720               6 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
         721                 :
         722               6 :   if (aCount < 1) {
         723               0 :     return NS_ERROR_DOM_TYPE_ERR;
         724                 :   }
         725                 :
         726              12 :   Key key;
         727               6 :   return ContinueInternal(key, aCount);
         728                 : }
         729                 :
         730                 : nsresult
         731            1778 : ContinueHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
         732                 : {
         733                 :   // We need to pick a query based on whether or not the cursor's mContinueToKey
         734                 :   // is set. If it is unset then othing was passed to continue so we'll grab the
         735                 :   // next item in the database that is greater than (less than, if we're running
         736                 :   // a PREV cursor) the current key. If it is set then a key was passed to
         737                 :   // continue so we'll grab the next item in the database that is greater than
         738                 :   // (less than, if we're running a PREV cursor) or equal to the key that was
         739                 :   // specified.
         740                 :
         741            3556 :   nsCAutoString query;
         742            1778 :   if (mCursor->mContinueToKey.IsUnset()) {
         743            1771 :     query.Assign(mCursor->mContinueQuery);
         744                 :   }
         745                 :   else {
         746               7 :     query.Assign(mCursor->mContinueToQuery);
         747                 :   }
         748            1778 :   NS_ASSERTION(!query.IsEmpty(), "Bad query!");
         749                 :
         750            1778 :   query.AppendInt(mCount);
         751                 :
         752            3556 :   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
         753            1778 :   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
         754                 :
         755            3556 :   mozStorageStatementScoper scoper(stmt);
         756                 :
         757            1778 :   nsresult rv = BindArgumentsToStatement(stmt);
         758            1778 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
         759                 :
         760            1778 :   NS_ASSERTION(mCount > 0, "Not ok!");
         761                 :
         762                 :   bool hasResult;
         763            3495 :   for (PRInt32 index = 0; index < mCount; index++) {
         764            1872 :     rv = stmt->ExecuteStep(&hasResult);
         765            1872 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
         766                 :
         767            1872 :     if (!hasResult) {
         768             155 :       break;
         769                 :     }
         770                 :   }
         771                 :
         772            1778 :   if (hasResult) {
         773            1623 :     rv = GatherResultsFromStatement(stmt);
         774            1623 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
         775                 :   }
         776                 :   else {
         777             155 :     mKey.Unset();
         778                 :   }
         779                 :
         780            1778 :   return NS_OK;
         781                 : }
         782                 :
         783                 : nsresult
         784            1778 : ContinueHelper::GetSuccessResult(JSContext* aCx,
         785                 :                                  jsval* aVal)
         786                 : {
         787                 :   // Remove cached stuff from last time.
         788            1778 :   mCursor->mCachedKey = JSVAL_VOID;
         789            1778 :   mCursor->mCachedPrimaryKey = JSVAL_VOID;
         790            1778 :   mCursor->mCachedValue = JSVAL_VOID;
         791            1778 :   mCursor->mHaveCachedKey = false;
         792            1778 :   mCursor->mHaveCachedPrimaryKey = false;
         793            1778 :   mCursor->mHaveCachedValue = false;
         794            1778 :   mCursor->mContinueCalled = false;
         795                 :
         796            1778 :   if (mKey.IsUnset()) {
         797             155 :     mCursor->mHaveValue = false;
         798             155 :     *aVal = JSVAL_VOID;
         799                 :   }
         800                 :   else {
         801            1623 :     NS_ASSERTION(mCursor->mType == IDBCursor::OBJECTSTORE ||
         802                 :                  !mObjectKey.IsUnset(), "Bad key!");
         803                 :
         804                 :     // Set new values.
         805            1623 :     mCursor->mKey = mKey;
         806            1623 :     mCursor->mObjectKey = mObjectKey;
         807            1623 :     mCursor->mContinueToKey.Unset();
         808                 :
         809            1623 :     mCursor->mCloneReadInfo.Swap(mCloneReadInfo);
         810            1623 :     mCloneReadInfo.mCloneBuffer.clear();
         811                 :
         812            1623 :     nsresult rv = WrapNative(aCx, mCursor, aVal);
         813            1623 :     NS_ENSURE_SUCCESS(rv, rv);
         814                 :   }
         815                 :
         816            1778 :   return NS_OK;
         817                 : }
         818                 :
         819                 : nsresult
         820            1323 : ContinueObjectStoreHelper::BindArgumentsToStatement(
         821                 :                                                mozIStorageStatement* aStatement)
         822                 : {
         823                 :   // Bind object store id.
         824            1323 :   nsresult rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("id"),
         825            1323 :                                             mCursor->mObjectStore->Id());
         826            1323 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
         827                 :
         828            2646 :   NS_NAMED_LITERAL_CSTRING(currentKeyName, "current_key");
         829            2646 :   NS_NAMED_LITERAL_CSTRING(rangeKeyName, "range_key");
         830                 :
         831                 :   // Bind current key.
         832            1323 :   const Key& currentKey = mCursor->mContinueToKey.IsUnset() ?
         833            1320 :                           mCursor->mKey :
         834            2643 :                           mCursor->mContinueToKey;
         835                 :
         836            1323 :   rv = currentKey.BindToStatement(aStatement, currentKeyName);
         837            1323 :   NS_ENSURE_SUCCESS(rv, rv);
         838                 :
         839                 :   // Bind range key if it is specified.
         840            1323 :   const Key& rangeKey = mCursor->mRangeKey;
         841                 :
         842            1323 :   if (!rangeKey.IsUnset()) {
         843               9 :     rv = rangeKey.BindToStatement(aStatement, rangeKeyName);
         844               9 :     NS_ENSURE_SUCCESS(rv, rv);
         845                 :   }
         846                 :
         847            1323 :   return NS_OK;
         848                 : }
         849                 :
         850                 : nsresult
         851            1289 : ContinueObjectStoreHelper::GatherResultsFromStatement(
         852                 :                                                mozIStorageStatement* aStatement)
         853                 : {
         854                 :   // Figure out what kind of key we have next.
         855            1289 :   nsresult rv = mKey.SetFromStatement(aStatement, 0);
         856            1289 :   NS_ENSURE_SUCCESS(rv, rv);
         857                 :
         858                 :   rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(aStatement, 1, 2,
         859            1289 :     mDatabase->Manager(), mCloneReadInfo);
         860            1289 :   NS_ENSURE_SUCCESS(rv, rv);
         861                 :
         862            1289 :   return NS_OK;
         863                 : }
         864                 :
         865                 : nsresult
         866             455 : ContinueIndexHelper::BindArgumentsToStatement(mozIStorageStatement* aStatement)
         867                 : {
         868                 :   // Bind index id.
         869             455 :   nsresult rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("id"),
         870             455 :                                             mCursor->mIndex->Id());
         871             455 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
         872                 :
         873             910 :   NS_NAMED_LITERAL_CSTRING(currentKeyName, "current_key");
         874                 :
         875                 :   // Bind current key.
         876             455 :   const Key& currentKey = mCursor->mContinueToKey.IsUnset() ?
         877             451 :                           mCursor->mKey :
         878             906 :                           mCursor->mContinueToKey;
         879                 :
         880             455 :   rv = currentKey.BindToStatement(aStatement, currentKeyName);
         881             455 :   NS_ENSURE_SUCCESS(rv, rv);
         882                 :
         883                 :   // Bind range key if it is specified.
         884             455 :   if (!mCursor->mRangeKey.IsUnset()) {
         885             276 :     NS_NAMED_LITERAL_CSTRING(rangeKeyName, "range_key");
         886             138 :     rv = mCursor->mRangeKey.BindToStatement(aStatement, rangeKeyName);
         887             138 :     NS_ENSURE_SUCCESS(rv, rv);
         888                 :   }
         889                 :
         890                 :   // Bind object key if duplicates are allowed and we're not continuing to a
         891                 :   // specific key.
         892             938 :   if ((mCursor->mDirection == IDBCursor::NEXT ||
         893              40 :        mCursor->mDirection == IDBCursor::PREV) &&
         894             443 :        mCursor->mContinueToKey.IsUnset()) {
         895             439 :     NS_ASSERTION(!mCursor->mObjectKey.IsUnset(), "Bad key!");
         896                 :
         897             878 :     NS_NAMED_LITERAL_CSTRING(objectKeyName, "object_key");
         898             439 :     rv = mCursor->mObjectKey.BindToStatement(aStatement, objectKeyName);
         899             439 :     NS_ENSURE_SUCCESS(rv, rv);
         900                 :   }
         901                 :
         902             455 :   return NS_OK;
         903                 : }
         904                 :
         905                 : nsresult
         906             207 : ContinueIndexHelper::GatherResultsFromStatement(
         907                 :                                                mozIStorageStatement* aStatement)
         908                 : {
         909             207 :   nsresult rv = mKey.SetFromStatement(aStatement, 0);
         910             207 :   NS_ENSURE_SUCCESS(rv, rv);
         911                 :
         912             207 :   rv = mObjectKey.SetFromStatement(aStatement, 1);
         913             207 :   NS_ENSURE_SUCCESS(rv, rv);
         914                 :
         915             207 :   return NS_OK;
         916                 : }
         917                 :
         918                 : nsresult
         919             127 : ContinueIndexObjectHelper::GatherResultsFromStatement(
         920                 :                                                mozIStorageStatement* aStatement)
         921                 : {
         922             127 :   nsresult rv = mKey.SetFromStatement(aStatement, 0);
         923             127 :   NS_ENSURE_SUCCESS(rv, rv);
         924                 :
         925             127 :   rv = mObjectKey.SetFromStatement(aStatement, 1);
         926             127 :   NS_ENSURE_SUCCESS(rv, rv);
         927                 :
         928                 :   rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(aStatement, 2, 3,
         929             127 :     mDatabase->Manager(), mCloneReadInfo);
         930             127 :   NS_ENSURE_SUCCESS(rv, rv);
         931                 :
         932             127 :   return NS_OK;
         933            4392 : }

Generated by: LCOV version 1.7