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 #ifndef mozilla_dom_idbrequest_h__ 8 #define mozilla_dom_idbrequest_h__ 9 10 #include "js/RootingAPI.h" 11 #include "mozilla/Attributes.h" 12 #include "mozilla/EventForwards.h" 13 #include "mozilla/dom/IDBRequestBinding.h" 14 #include "mozilla/dom/ScriptSettings.h" 15 #include "mozilla/DOMEventTargetHelper.h" 16 #include "mozilla/HoldDropJSObjects.h" 17 #include "nsCycleCollectionParticipant.h" 18 #include "ReportInternalError.h" 19 #include "SafeRefPtr.h" 20 21 #define PRIVATE_IDBREQUEST_IID \ 22 { \ 23 0xe68901e5, 0x1d50, 0x4ee9, { \ 24 0xaf, 0x49, 0x90, 0x99, 0x4a, 0xff, 0xc8, 0x39 \ 25 } \ 26 } 27 28 class nsIGlobalObject; 29 30 namespace mozilla { 31 32 class ErrorResult; 33 34 namespace dom { 35 36 class DOMException; 37 class IDBCursor; 38 class IDBDatabase; 39 class IDBFactory; 40 class IDBIndex; 41 class IDBObjectStore; 42 class IDBTransaction; 43 template <typename> 44 struct Nullable; 45 class OwningIDBObjectStoreOrIDBIndexOrIDBCursor; 46 class StrongWorkerRef; 47 48 class IDBRequest : public DOMEventTargetHelper { 49 protected: 50 // mSourceAsObjectStore and mSourceAsIndex are exclusive and one must always 51 // be set. mSourceAsCursor is sometimes set also. 52 RefPtr<IDBObjectStore> mSourceAsObjectStore; 53 RefPtr<IDBIndex> mSourceAsIndex; 54 RefPtr<IDBCursor> mSourceAsCursor; 55 56 SafeRefPtr<IDBTransaction> mTransaction; 57 58 JS::Heap<JS::Value> mResultVal; 59 RefPtr<DOMException> mError; 60 61 nsString mFilename; 62 uint64_t mLoggingSerialNumber; 63 nsresult mErrorCode; 64 uint32_t mLineNo; 65 uint32_t mColumn; 66 bool mHaveResultOrErrorCode; 67 68 public: 69 [[nodiscard]] static MovingNotNull<RefPtr<IDBRequest>> Create( 70 JSContext* aCx, IDBDatabase* aDatabase, 71 SafeRefPtr<IDBTransaction> aTransaction); 72 73 [[nodiscard]] static MovingNotNull<RefPtr<IDBRequest>> Create( 74 JSContext* aCx, IDBObjectStore* aSource, IDBDatabase* aDatabase, 75 SafeRefPtr<IDBTransaction> aTransaction); 76 77 [[nodiscard]] static MovingNotNull<RefPtr<IDBRequest>> Create( 78 JSContext* aCx, IDBIndex* aSource, IDBDatabase* aDatabase, 79 SafeRefPtr<IDBTransaction> aTransaction); 80 81 static void CaptureCaller(JSContext* aCx, nsAString& aFilename, 82 uint32_t* aLineNo, uint32_t* aColumn); 83 84 static uint64_t NextSerialNumber(); 85 86 // EventTarget 87 void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; 88 89 void GetSource( 90 Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const; 91 92 void Reset(); 93 94 template <typename ResultCallback> SetResult(const ResultCallback & aCallback)95 void SetResult(const ResultCallback& aCallback) { 96 AssertIsOnOwningThread(); 97 MOZ_ASSERT(!mHaveResultOrErrorCode); 98 MOZ_ASSERT(mResultVal.isUndefined()); 99 MOZ_ASSERT(!mError); 100 101 // Already disconnected from the owner. 102 if (!GetOwnerGlobal()) { 103 SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); 104 return; 105 } 106 107 // See this global is still valid. 108 if (NS_WARN_IF(NS_FAILED(CheckCurrentGlobalCorrectness()))) { 109 SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); 110 return; 111 } 112 113 AutoJSAPI autoJS; 114 if (!autoJS.Init(GetOwnerGlobal())) { 115 IDB_WARNING("Failed to initialize AutoJSAPI!"); 116 SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); 117 return; 118 } 119 120 JSContext* cx = autoJS.cx(); 121 122 JS::Rooted<JS::Value> result(cx); 123 nsresult rv = aCallback(cx, &result); 124 if (NS_WARN_IF(NS_FAILED(rv))) { 125 // This can only fail if the structured clone contains a mutable file 126 // and the child is not in the main thread and main process. 127 // In that case CreateAndWrapMutableFile() returns false which shows up 128 // as NS_ERROR_DOM_DATA_CLONE_ERR here. 129 MOZ_ASSERT(rv == NS_ERROR_DOM_DATA_CLONE_ERR); 130 131 // We are not setting a result or an error object here since we want to 132 // throw an exception when the 'result' property is being touched. 133 return; 134 } 135 136 mError = nullptr; 137 138 mResultVal = result; 139 mozilla::HoldJSObjects(this); 140 141 mHaveResultOrErrorCode = true; 142 } 143 144 void SetError(nsresult aRv); 145 146 nsresult GetErrorCode() const 147 #ifdef DEBUG 148 ; 149 #else 150 { 151 return mErrorCode; 152 } 153 #endif 154 155 DOMException* GetErrorAfterResult() const 156 #ifdef DEBUG 157 ; 158 #else 159 { 160 return mError; 161 } 162 #endif 163 164 DOMException* GetError(ErrorResult& aRv); 165 166 void GetCallerLocation(nsAString& aFilename, uint32_t* aLineNo, 167 uint32_t* aColumn) const; 168 IsPending()169 bool IsPending() const { return !mHaveResultOrErrorCode; } 170 LoggingSerialNumber()171 uint64_t LoggingSerialNumber() const { 172 AssertIsOnOwningThread(); 173 174 return mLoggingSerialNumber; 175 } 176 177 void SetLoggingSerialNumber(uint64_t aLoggingSerialNumber); 178 GetParentObject()179 nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); } 180 181 void GetResult(JS::MutableHandle<JS::Value> aResult, ErrorResult& aRv) const; 182 GetResult(JSContext * aCx,JS::MutableHandle<JS::Value> aResult,ErrorResult & aRv)183 void GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult, 184 ErrorResult& aRv) const { 185 GetResult(aResult, aRv); 186 } 187 MaybeTransactionRef()188 Maybe<IDBTransaction&> MaybeTransactionRef() const { 189 AssertIsOnOwningThread(); 190 191 return mTransaction.maybeDeref(); 192 } 193 MutableTransactionRef()194 IDBTransaction& MutableTransactionRef() const { 195 AssertIsOnOwningThread(); 196 197 return *mTransaction; 198 } 199 AcquireTransaction()200 SafeRefPtr<IDBTransaction> AcquireTransaction() const { 201 AssertIsOnOwningThread(); 202 203 return mTransaction.clonePtr(); 204 } 205 206 // For WebIDL binding. GetTransaction()207 RefPtr<IDBTransaction> GetTransaction() const { 208 AssertIsOnOwningThread(); 209 210 return AsRefPtr(mTransaction.clonePtr()); 211 } 212 213 IDBRequestReadyState ReadyState() const; 214 215 void SetSource(IDBCursor* aSource); 216 217 IMPL_EVENT_HANDLER(success); 218 IMPL_EVENT_HANDLER(error); 219 AssertIsOnOwningThread()220 void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(IDBRequest); } 221 222 NS_DECL_ISUPPORTS_INHERITED 223 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBRequest, 224 DOMEventTargetHelper) 225 226 // nsWrapperCache 227 virtual JSObject* WrapObject(JSContext* aCx, 228 JS::Handle<JSObject*> aGivenProto) override; 229 230 protected: 231 explicit IDBRequest(IDBDatabase* aDatabase); 232 explicit IDBRequest(nsIGlobalObject* aGlobal); 233 ~IDBRequest(); 234 235 void InitMembers(); 236 237 void ConstructResult(); 238 }; 239 240 class IDBOpenDBRequest final : public IDBRequest { 241 // Only touched on the owning thread. 242 SafeRefPtr<IDBFactory> mFactory; 243 244 RefPtr<StrongWorkerRef> mWorkerRef; 245 246 const bool mFileHandleDisabled; 247 bool mIncreasedActiveDatabaseCount; 248 249 public: 250 [[nodiscard]] static RefPtr<IDBOpenDBRequest> Create( 251 JSContext* aCx, SafeRefPtr<IDBFactory> aFactory, 252 nsIGlobalObject* aGlobal); 253 IsFileHandleDisabled()254 bool IsFileHandleDisabled() const { return mFileHandleDisabled; } 255 256 void SetTransaction(SafeRefPtr<IDBTransaction> aTransaction); 257 258 void DispatchNonTransactionError(nsresult aErrorCode); 259 260 void NoteComplete(); 261 262 // EventTarget 263 virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; 264 265 IMPL_EVENT_HANDLER(blocked); 266 IMPL_EVENT_HANDLER(upgradeneeded); 267 268 NS_DECL_ISUPPORTS_INHERITED 269 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBOpenDBRequest, IDBRequest) 270 271 // nsWrapperCache 272 virtual JSObject* WrapObject(JSContext* aCx, 273 JS::Handle<JSObject*> aGivenProto) override; 274 275 private: 276 IDBOpenDBRequest(SafeRefPtr<IDBFactory> aFactory, nsIGlobalObject* aGlobal, 277 bool aFileHandleDisabled); 278 279 ~IDBOpenDBRequest(); 280 281 void IncreaseActiveDatabaseCount(); 282 283 void MaybeDecreaseActiveDatabaseCount(); 284 }; 285 286 } // namespace dom 287 } // namespace mozilla 288 289 #endif // mozilla_dom_idbrequest_h__ 290