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 /* 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/. */
7 #include "IndexedDatabaseManager.h"
9 #include "nsIConsoleService.h"
10 #include "nsIDiskSpaceWatcher.h"
12 #include "nsIObserverService.h"
13 #include "nsIScriptError.h"
16 #include "mozilla/ClearOnShutdown.h"
17 #include "mozilla/CondVar.h"
18 #include "mozilla/ContentEvents.h"
19 #include "mozilla/dom/ErrorEventBinding.h"
20 #include "mozilla/dom/quota/OriginOrPatternString.h"
21 #include "mozilla/dom/quota/QuotaManager.h"
22 #include "mozilla/dom/quota/Utilities.h"
23 #include "mozilla/dom/TabContext.h"
24 #include "mozilla/EventDispatcher.h"
25 #include "mozilla/Services.h"
26 #include "mozilla/Preferences.h"
27 #include "mozilla/storage.h"
28 #include "nsContentUtils.h"
29 #include "nsThreadUtils.h"
31 #include "IDBEvents.h"
32 #include "IDBFactory.h"
33 #include "IDBKeyRange.h"
34 #include "IDBRequest.h"
36 // Bindings for ResolveConstructors
37 #include "mozilla/dom/IDBCursorBinding.h"
38 #include "mozilla/dom/IDBDatabaseBinding.h"
39 #include "mozilla/dom/IDBFactoryBinding.h"
40 #include "mozilla/dom/IDBIndexBinding.h"
41 #include "mozilla/dom/IDBKeyRangeBinding.h"
42 #include "mozilla/dom/IDBMutableFileBinding.h"
43 #include "mozilla/dom/IDBObjectStoreBinding.h"
44 #include "mozilla/dom/IDBOpenDBRequestBinding.h"
45 #include "mozilla/dom/IDBRequestBinding.h"
46 #include "mozilla/dom/IDBTransactionBinding.h"
47 #include "mozilla/dom/IDBVersionChangeEventBinding.h"
49 #define IDB_STR "indexedDB"
51 // The two possible values for the data argument when receiving the disk space
52 // observer notification.
53 #define LOW_DISK_SPACE_DATA_FULL "full"
54 #define LOW_DISK_SPACE_DATA_FREE "free"
56 USING_INDEXEDDB_NAMESPACE
57 using namespace mozilla
;
58 using namespace mozilla::dom
;
61 BEGIN_INDEXEDDB_NAMESPACE
66 already_AddRefed
<FileManager
>
67 GetFileManager(PersistenceType aPersistenceType
,
68 const nsAString
& aName
) const;
71 AddFileManager(FileManager
* aFileManager
);
74 HasFileManagers() const
78 return !mPersistentStorageFileManagers
.IsEmpty() ||
79 !mTemporaryStorageFileManagers
.IsEmpty();
83 InvalidateAllFileManagers() const;
86 InvalidateAndRemoveFileManagers(PersistenceType aPersistenceType
);
89 InvalidateAndRemoveFileManager(PersistenceType aPersistenceType
,
90 const nsAString
& aName
);
93 nsTArray
<nsRefPtr
<FileManager
> >&
94 GetArray(PersistenceType aPersistenceType
);
96 const nsTArray
<nsRefPtr
<FileManager
> >&
97 GetImmutableArray(PersistenceType aPersistenceType
) const
99 return const_cast<FileManagerInfo
*>(this)->GetArray(aPersistenceType
);
102 nsTArray
<nsRefPtr
<FileManager
> > mPersistentStorageFileManagers
;
103 nsTArray
<nsRefPtr
<FileManager
> > mTemporaryStorageFileManagers
;
106 END_INDEXEDDB_NAMESPACE
110 mozilla::StaticRefPtr
<IndexedDatabaseManager
> gDBManager
;
112 mozilla::Atomic
<bool> gInitialized(false);
113 mozilla::Atomic
<bool> gClosed(false);
115 class AsyncDeleteFileRunnable MOZ_FINAL
: public nsIRunnable
118 NS_DECL_THREADSAFE_ISUPPORTS
121 AsyncDeleteFileRunnable(FileManager
* aFileManager
, int64_t aFileId
);
124 ~AsyncDeleteFileRunnable() {}
126 nsRefPtr
<FileManager
> mFileManager
;
130 class GetFileReferencesHelper MOZ_FINAL
: public nsIRunnable
133 NS_DECL_THREADSAFE_ISUPPORTS
136 GetFileReferencesHelper(PersistenceType aPersistenceType
,
137 const nsACString
& aOrigin
,
138 const nsAString
& aDatabaseName
,
140 : mPersistenceType(aPersistenceType
),
142 mDatabaseName(aDatabaseName
),
144 mMutex(IndexedDatabaseManager::FileMutex()),
145 mCondVar(mMutex
, "GetFileReferencesHelper::mCondVar"),
154 DispatchAndReturnFileReferences(int32_t* aMemRefCnt
,
156 int32_t* aSliceRefCnt
,
160 ~GetFileReferencesHelper() {}
162 PersistenceType mPersistenceType
;
164 nsString mDatabaseName
;
167 mozilla::Mutex
& mMutex
;
168 mozilla::CondVar mCondVar
;
171 int32_t mSliceRefCnt
;
176 struct MOZ_STACK_CLASS InvalidateInfo
178 InvalidateInfo(PersistenceType aPersistenceType
, const nsACString
& aPattern
)
179 : persistenceType(aPersistenceType
), pattern(aPattern
)
182 PersistenceType persistenceType
;
183 const nsACString
& pattern
;
186 } // anonymous namespace
188 IndexedDatabaseManager::IndexedDatabaseManager()
189 : mFileMutex("IndexedDatabaseManager.mFileMutex")
191 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
194 IndexedDatabaseManager::~IndexedDatabaseManager()
196 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
199 bool IndexedDatabaseManager::sIsMainProcess
= false;
200 mozilla::Atomic
<bool> IndexedDatabaseManager::sLowDiskSpaceMode(false);
203 IndexedDatabaseManager
*
204 IndexedDatabaseManager::GetOrCreate()
206 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
209 NS_ERROR("Calling GetOrCreate() after shutdown!");
214 sIsMainProcess
= XRE_GetProcessType() == GeckoProcessType_Default
;
216 if (sIsMainProcess
&& Preferences::GetBool("disk_space_watcher.enabled", false)) {
217 // See if we're starting up in low disk space conditions.
218 nsCOMPtr
<nsIDiskSpaceWatcher
> watcher
=
219 do_GetService(DISKSPACEWATCHER_CONTRACTID
);
222 if (NS_SUCCEEDED(watcher
->GetIsDiskFull(&isDiskFull
))) {
223 sLowDiskSpaceMode
= isDiskFull
;
226 NS_WARNING("GetIsDiskFull failed!");
230 NS_WARNING("No disk space watcher component available!");
234 nsRefPtr
<IndexedDatabaseManager
> instance(new IndexedDatabaseManager());
236 nsresult rv
= instance
->Init();
237 NS_ENSURE_SUCCESS(rv
, nullptr);
239 if (gInitialized
.exchange(true)) {
240 NS_ERROR("Initialized more than once?!");
243 gDBManager
= instance
;
245 ClearOnShutdown(&gDBManager
);
252 IndexedDatabaseManager
*
253 IndexedDatabaseManager::Get()
255 // Does not return an owning reference.
260 IndexedDatabaseManager::Init()
262 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
264 // Make sure that the quota manager is up.
265 QuotaManager
* qm
= QuotaManager::GetOrCreate();
268 // During Init() we can't yet call IsMainProcess(), just check sIsMainProcess
270 if (sIsMainProcess
) {
271 // Must initialize the storage service on the main thread.
272 nsCOMPtr
<mozIStorageService
> ss
=
273 do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID
);
276 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
277 NS_ENSURE_STATE(obs
);
280 obs
->AddObserver(this, DISKSPACEWATCHER_OBSERVER_TOPIC
, false);
281 NS_ENSURE_SUCCESS(rv
, rv
);
288 IndexedDatabaseManager::Destroy()
290 // Setting the closed flag prevents the service from being recreated.
291 // Don't set it though if there's no real instance created.
292 if (gInitialized
&& gClosed
.exchange(true)) {
293 NS_ERROR("Shutdown more than once?!");
301 IndexedDatabaseManager::FireWindowOnError(nsPIDOMWindow
* aOwner
,
302 EventChainPostVisitor
& aVisitor
)
304 NS_ENSURE_TRUE(aVisitor
.mDOMEvent
, NS_ERROR_UNEXPECTED
);
309 if (aVisitor
.mEventStatus
== nsEventStatus_eConsumeNoDefault
) {
314 nsresult rv
= aVisitor
.mDOMEvent
->GetType(type
);
315 NS_ENSURE_SUCCESS(rv
, rv
);
317 if (!type
.EqualsLiteral(ERROR_EVT_STR
)) {
321 nsCOMPtr
<EventTarget
> eventTarget
=
322 aVisitor
.mDOMEvent
->InternalDOMEvent()->GetTarget();
324 IDBRequest
* request
= static_cast<IDBRequest
*>(eventTarget
.get());
325 NS_ENSURE_TRUE(request
, NS_ERROR_UNEXPECTED
);
328 nsRefPtr
<DOMError
> error
= request
->GetError(ret
);
330 return ret
.ErrorCode();
335 error
->GetName(errorName
);
338 ThreadsafeAutoJSContext cx
;
339 RootedDictionary
<ErrorEventInit
> init(cx
);
340 request
->FillScriptErrorEvent(init
);
342 init
.mMessage
= errorName
;
343 init
.mCancelable
= true;
344 init
.mBubbles
= true;
346 nsCOMPtr
<nsIScriptGlobalObject
> sgo(do_QueryInterface(aOwner
));
347 NS_ASSERTION(sgo
, "How can this happen?!");
349 nsEventStatus status
= nsEventStatus_eIgnore
;
350 if (NS_FAILED(sgo
->HandleScriptError(init
, &status
))) {
351 NS_WARNING("Failed to dispatch script error event");
352 status
= nsEventStatus_eIgnore
;
355 bool preventDefaultCalled
= status
== nsEventStatus_eConsumeNoDefault
;
356 if (preventDefaultCalled
) {
360 // Log an error to the error console.
361 nsCOMPtr
<nsIScriptError
> scriptError
=
362 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID
, &rv
);
363 NS_ENSURE_SUCCESS(rv
, rv
);
365 if (NS_FAILED(scriptError
->InitWithWindowID(errorName
,
367 EmptyString(), init
.mLineno
,
370 aOwner
->WindowID()))) {
371 NS_WARNING("Failed to init script error!");
372 return NS_ERROR_FAILURE
;
375 nsCOMPtr
<nsIConsoleService
> consoleService
=
376 do_GetService(NS_CONSOLESERVICE_CONTRACTID
, &rv
);
377 NS_ENSURE_SUCCESS(rv
, rv
);
379 return consoleService
->LogMessage(scriptError
);
384 IndexedDatabaseManager::TabContextMayAccessOrigin(const TabContext
& aContext
,
385 const nsACString
& aOrigin
)
387 NS_ASSERTION(!aOrigin
.IsEmpty(), "Empty origin!");
389 // If aContext is for a browser element, it's allowed only to access other
390 // browser elements. But if aContext is not for a browser element, it may
391 // access both browser and non-browser elements.
392 nsAutoCString pattern
;
393 QuotaManager::GetOriginPatternStringMaybeIgnoreBrowser(
394 aContext
.OwnOrContainingAppId(),
395 aContext
.IsBrowserElement(),
398 return PatternMatchesOrigin(pattern
, aOrigin
);
403 IndexedDatabaseManager::DefineIndexedDB(JSContext
* aCx
,
404 JS::Handle
<JSObject
*> aGlobal
)
406 MOZ_ASSERT(NS_IsMainThread());
407 MOZ_ASSERT(nsContentUtils::IsCallerChrome(), "Only for chrome!");
408 MOZ_ASSERT(js::GetObjectClass(aGlobal
)->flags
& JSCLASS_DOM_GLOBAL
,
409 "Passed object is not a global object!");
411 if (!IDBCursorBinding::GetConstructorObject(aCx
, aGlobal
) ||
412 !IDBCursorWithValueBinding::GetConstructorObject(aCx
, aGlobal
) ||
413 !IDBDatabaseBinding::GetConstructorObject(aCx
, aGlobal
) ||
414 !IDBFactoryBinding::GetConstructorObject(aCx
, aGlobal
) ||
415 !IDBIndexBinding::GetConstructorObject(aCx
, aGlobal
) ||
416 !IDBKeyRangeBinding::GetConstructorObject(aCx
, aGlobal
) ||
417 !IDBMutableFileBinding::GetConstructorObject(aCx
, aGlobal
) ||
418 !IDBObjectStoreBinding::GetConstructorObject(aCx
, aGlobal
) ||
419 !IDBOpenDBRequestBinding::GetConstructorObject(aCx
, aGlobal
) ||
420 !IDBRequestBinding::GetConstructorObject(aCx
, aGlobal
) ||
421 !IDBTransactionBinding::GetConstructorObject(aCx
, aGlobal
) ||
422 !IDBVersionChangeEventBinding::GetConstructorObject(aCx
, aGlobal
))
427 nsRefPtr
<IDBFactory
> factory
;
428 if (NS_FAILED(IDBFactory::Create(aCx
, aGlobal
, nullptr,
429 getter_AddRefs(factory
)))) {
433 MOZ_ASSERT(factory
, "This should never fail for chrome!");
435 JS::Rooted
<JS::Value
> indexedDB(aCx
);
436 js::AssertSameCompartment(aCx
, aGlobal
);
437 if (!WrapNewBindingObject(aCx
, factory
, &indexedDB
)) {
441 return JS_DefineProperty(aCx
, aGlobal
, IDB_STR
, indexedDB
, JSPROP_ENUMERATE
);
446 IndexedDatabaseManager::IsClosed()
454 IndexedDatabaseManager::IsMainProcess()
456 NS_ASSERTION(gDBManager
,
457 "IsMainProcess() called before indexedDB has been initialized!");
458 NS_ASSERTION((XRE_GetProcessType() == GeckoProcessType_Default
) ==
459 sIsMainProcess
, "XRE_GetProcessType changed its tune!");
460 return sIsMainProcess
;
465 IndexedDatabaseManager::InLowDiskSpaceMode()
467 NS_ASSERTION(gDBManager
,
468 "InLowDiskSpaceMode() called before indexedDB has been "
470 return sLowDiskSpaceMode
;
474 already_AddRefed
<FileManager
>
475 IndexedDatabaseManager::GetFileManager(PersistenceType aPersistenceType
,
476 const nsACString
& aOrigin
,
477 const nsAString
& aDatabaseName
)
479 AssertIsOnIOThread();
481 FileManagerInfo
* info
;
482 if (!mFileManagerInfos
.Get(aOrigin
, &info
)) {
486 nsRefPtr
<FileManager
> fileManager
=
487 info
->GetFileManager(aPersistenceType
, aDatabaseName
);
489 return fileManager
.forget();
493 IndexedDatabaseManager::AddFileManager(FileManager
* aFileManager
)
495 AssertIsOnIOThread();
496 NS_ASSERTION(aFileManager
, "Null file manager!");
498 FileManagerInfo
* info
;
499 if (!mFileManagerInfos
.Get(aFileManager
->Origin(), &info
)) {
500 info
= new FileManagerInfo();
501 mFileManagerInfos
.Put(aFileManager
->Origin(), info
);
504 info
->AddFileManager(aFileManager
);
509 IndexedDatabaseManager::InvalidateAndRemoveFileManagers(
510 const nsACString
& aKey
,
511 nsAutoPtr
<FileManagerInfo
>& aValue
,
514 AssertIsOnIOThread();
515 NS_ASSERTION(!aKey
.IsEmpty(), "Empty key!");
516 NS_ASSERTION(aValue
, "Null pointer!");
519 aValue
->InvalidateAllFileManagers();
520 return PL_DHASH_REMOVE
;
523 InvalidateInfo
* info
= static_cast<InvalidateInfo
*>(aUserArg
);
525 if (PatternMatchesOrigin(info
->pattern
, aKey
)) {
526 aValue
->InvalidateAndRemoveFileManagers(info
->persistenceType
);
528 if (!aValue
->HasFileManagers()) {
529 return PL_DHASH_REMOVE
;
533 return PL_DHASH_NEXT
;
537 IndexedDatabaseManager::InvalidateAllFileManagers()
539 AssertIsOnIOThread();
541 mFileManagerInfos
.Enumerate(InvalidateAndRemoveFileManagers
, nullptr);
545 IndexedDatabaseManager::InvalidateFileManagers(
546 PersistenceType aPersistenceType
,
547 const OriginOrPatternString
& aOriginOrPattern
)
549 AssertIsOnIOThread();
550 NS_ASSERTION(!aOriginOrPattern
.IsEmpty(), "Empty pattern!");
552 if (aOriginOrPattern
.IsOrigin()) {
553 FileManagerInfo
* info
;
554 if (!mFileManagerInfos
.Get(aOriginOrPattern
, &info
)) {
558 info
->InvalidateAndRemoveFileManagers(aPersistenceType
);
560 if (!info
->HasFileManagers()) {
561 mFileManagerInfos
.Remove(aOriginOrPattern
);
565 InvalidateInfo
info(aPersistenceType
, aOriginOrPattern
);
566 mFileManagerInfos
.Enumerate(InvalidateAndRemoveFileManagers
, &info
);
571 IndexedDatabaseManager::InvalidateFileManager(PersistenceType aPersistenceType
,
572 const nsACString
& aOrigin
,
573 const nsAString
& aDatabaseName
)
575 AssertIsOnIOThread();
577 FileManagerInfo
* info
;
578 if (!mFileManagerInfos
.Get(aOrigin
, &info
)) {
582 info
->InvalidateAndRemoveFileManager(aPersistenceType
, aDatabaseName
);
584 if (!info
->HasFileManagers()) {
585 mFileManagerInfos
.Remove(aOrigin
);
590 IndexedDatabaseManager::AsyncDeleteFile(FileManager
* aFileManager
,
593 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
595 NS_ENSURE_ARG_POINTER(aFileManager
);
597 QuotaManager
* quotaManager
= QuotaManager::Get();
598 NS_ASSERTION(quotaManager
, "Shouldn't be null!");
600 // See if we're currently clearing the storages for this origin. If so then
601 // we pretend that we've already deleted everything.
602 if (quotaManager
->IsClearOriginPending(
603 aFileManager
->Origin(),
604 Nullable
<PersistenceType
>(aFileManager
->Type()))) {
608 nsRefPtr
<AsyncDeleteFileRunnable
> runnable
=
609 new AsyncDeleteFileRunnable(aFileManager
, aFileId
);
612 quotaManager
->IOThread()->Dispatch(runnable
, NS_DISPATCH_NORMAL
);
613 NS_ENSURE_SUCCESS(rv
, rv
);
619 IndexedDatabaseManager::BlockAndGetFileReferences(
620 PersistenceType aPersistenceType
,
621 const nsACString
& aOrigin
,
622 const nsAString
& aDatabaseName
,
626 int32_t* aSliceRefCnt
,
629 nsRefPtr
<GetFileReferencesHelper
> helper
=
630 new GetFileReferencesHelper(aPersistenceType
, aOrigin
, aDatabaseName
,
633 nsresult rv
= helper
->DispatchAndReturnFileReferences(aRefCnt
, aDBRefCnt
,
634 aSliceRefCnt
, aResult
);
635 NS_ENSURE_SUCCESS(rv
, rv
);
640 NS_IMPL_ADDREF(IndexedDatabaseManager
)
641 NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager
, Destroy())
642 NS_IMPL_QUERY_INTERFACE(IndexedDatabaseManager
, nsIObserver
)
645 IndexedDatabaseManager::Observe(nsISupports
* aSubject
, const char* aTopic
,
646 const char16_t
* aData
)
648 NS_ASSERTION(IsMainProcess(), "Wrong process!");
649 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
651 if (!strcmp(aTopic
, DISKSPACEWATCHER_OBSERVER_TOPIC
)) {
652 NS_ASSERTION(aData
, "No data?!");
654 const nsDependentString
data(aData
);
656 if (data
.EqualsLiteral(LOW_DISK_SPACE_DATA_FULL
)) {
657 sLowDiskSpaceMode
= true;
659 else if (data
.EqualsLiteral(LOW_DISK_SPACE_DATA_FREE
)) {
660 sLowDiskSpaceMode
= false;
663 NS_NOTREACHED("Unknown data value!");
669 NS_NOTREACHED("Unknown topic!");
670 return NS_ERROR_UNEXPECTED
;
673 already_AddRefed
<FileManager
>
674 FileManagerInfo::GetFileManager(PersistenceType aPersistenceType
,
675 const nsAString
& aName
) const
677 AssertIsOnIOThread();
679 const nsTArray
<nsRefPtr
<FileManager
> >& managers
=
680 GetImmutableArray(aPersistenceType
);
682 for (uint32_t i
= 0; i
< managers
.Length(); i
++) {
683 const nsRefPtr
<FileManager
>& fileManager
= managers
[i
];
685 if (fileManager
->DatabaseName() == aName
) {
686 nsRefPtr
<FileManager
> result
= fileManager
;
687 return result
.forget();
695 FileManagerInfo::AddFileManager(FileManager
* aFileManager
)
697 AssertIsOnIOThread();
699 nsTArray
<nsRefPtr
<FileManager
> >& managers
= GetArray(aFileManager
->Type());
701 NS_ASSERTION(!managers
.Contains(aFileManager
), "Adding more than once?!");
703 managers
.AppendElement(aFileManager
);
707 FileManagerInfo::InvalidateAllFileManagers() const
709 AssertIsOnIOThread();
713 for (i
= 0; i
< mPersistentStorageFileManagers
.Length(); i
++) {
714 mPersistentStorageFileManagers
[i
]->Invalidate();
717 for (i
= 0; i
< mTemporaryStorageFileManagers
.Length(); i
++) {
718 mTemporaryStorageFileManagers
[i
]->Invalidate();
723 FileManagerInfo::InvalidateAndRemoveFileManagers(
724 PersistenceType aPersistenceType
)
726 AssertIsOnIOThread();
728 nsTArray
<nsRefPtr
<FileManager
> >& managers
= GetArray(aPersistenceType
);
730 for (uint32_t i
= 0; i
< managers
.Length(); i
++) {
731 managers
[i
]->Invalidate();
738 FileManagerInfo::InvalidateAndRemoveFileManager(
739 PersistenceType aPersistenceType
,
740 const nsAString
& aName
)
742 AssertIsOnIOThread();
744 nsTArray
<nsRefPtr
<FileManager
> >& managers
= GetArray(aPersistenceType
);
746 for (uint32_t i
= 0; i
< managers
.Length(); i
++) {
747 nsRefPtr
<FileManager
>& fileManager
= managers
[i
];
748 if (fileManager
->DatabaseName() == aName
) {
749 fileManager
->Invalidate();
750 managers
.RemoveElementAt(i
);
756 nsTArray
<nsRefPtr
<FileManager
> >&
757 FileManagerInfo::GetArray(PersistenceType aPersistenceType
)
759 switch (aPersistenceType
) {
760 case PERSISTENCE_TYPE_PERSISTENT
:
761 return mPersistentStorageFileManagers
;
762 case PERSISTENCE_TYPE_TEMPORARY
:
763 return mTemporaryStorageFileManagers
;
765 case PERSISTENCE_TYPE_INVALID
:
767 MOZ_CRASH("Bad storage type value!");
768 return mPersistentStorageFileManagers
;
772 AsyncDeleteFileRunnable::AsyncDeleteFileRunnable(FileManager
* aFileManager
,
774 : mFileManager(aFileManager
), mFileId(aFileId
)
778 NS_IMPL_ISUPPORTS(AsyncDeleteFileRunnable
,
782 AsyncDeleteFileRunnable::Run()
784 AssertIsOnIOThread();
786 nsCOMPtr
<nsIFile
> directory
= mFileManager
->GetDirectory();
787 NS_ENSURE_TRUE(directory
, NS_ERROR_FAILURE
);
789 nsCOMPtr
<nsIFile
> file
= mFileManager
->GetFileForId(directory
, mFileId
);
790 NS_ENSURE_TRUE(file
, NS_ERROR_FAILURE
);
795 if (mFileManager
->Privilege() != Chrome
) {
796 rv
= file
->GetFileSize(&fileSize
);
797 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
800 rv
= file
->Remove(false);
801 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
803 if (mFileManager
->Privilege() != Chrome
) {
804 QuotaManager
* quotaManager
= QuotaManager::Get();
805 NS_ASSERTION(quotaManager
, "Shouldn't be null!");
807 quotaManager
->DecreaseUsageForOrigin(mFileManager
->Type(),
808 mFileManager
->Group(),
809 mFileManager
->Origin(), fileSize
);
812 directory
= mFileManager
->GetJournalDirectory();
813 NS_ENSURE_TRUE(directory
, NS_ERROR_FAILURE
);
815 file
= mFileManager
->GetFileForId(directory
, mFileId
);
816 NS_ENSURE_TRUE(file
, NS_ERROR_FAILURE
);
818 rv
= file
->Remove(false);
819 NS_ENSURE_SUCCESS(rv
, rv
);
825 GetFileReferencesHelper::DispatchAndReturnFileReferences(int32_t* aMemRefCnt
,
827 int32_t* aSliceRefCnt
,
830 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
832 QuotaManager
* quotaManager
= QuotaManager::Get();
833 NS_ASSERTION(quotaManager
, "Shouldn't be null!");
836 quotaManager
->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL
);
837 NS_ENSURE_SUCCESS(rv
, rv
);
839 mozilla::MutexAutoLock
autolock(mMutex
);
844 *aMemRefCnt
= mMemRefCnt
;
845 *aDBRefCnt
= mDBRefCnt
;
846 *aSliceRefCnt
= mSliceRefCnt
;
852 NS_IMPL_ISUPPORTS(GetFileReferencesHelper
,
856 GetFileReferencesHelper::Run()
858 AssertIsOnIOThread();
860 IndexedDatabaseManager
* mgr
= IndexedDatabaseManager::Get();
861 NS_ASSERTION(mgr
, "This should never fail!");
863 nsRefPtr
<FileManager
> fileManager
=
864 mgr
->GetFileManager(mPersistenceType
, mOrigin
, mDatabaseName
);
867 nsRefPtr
<FileInfo
> fileInfo
= fileManager
->GetFileInfo(mFileId
);
870 fileInfo
->GetReferences(&mMemRefCnt
, &mDBRefCnt
, &mSliceRefCnt
);
872 if (mMemRefCnt
!= -1) {
873 // We added an extra temp ref, so account for that accordingly.
881 mozilla::MutexAutoLock
lock(mMutex
);
882 NS_ASSERTION(mWaiting
, "Huh?!");