michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_dom_file_fileservice_h__ michael@0: #define mozilla_dom_file_fileservice_h__ michael@0: michael@0: #include "FileCommon.h" michael@0: michael@0: #include "nsIObserver.h" michael@0: michael@0: #include "nsClassHashtable.h" michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: #include "mozilla/dom/file/FileHelper.h" michael@0: #include "mozilla/dom/file/LockedFile.h" michael@0: michael@0: BEGIN_FILE_NAMESPACE michael@0: michael@0: class FileService MOZ_FINAL : public nsIObserver michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: // Returns a non-owning reference! michael@0: static FileService* michael@0: GetOrCreate(); michael@0: michael@0: // Returns a non-owning reference! michael@0: static FileService* michael@0: Get(); michael@0: michael@0: static void michael@0: Shutdown(); michael@0: michael@0: // Returns true if we've begun the shutdown process. michael@0: static bool michael@0: IsShuttingDown(); michael@0: michael@0: nsresult michael@0: Enqueue(LockedFile* aLockedFile, FileHelper* aFileHelper); michael@0: michael@0: void michael@0: NotifyLockedFileCompleted(LockedFile* aLockedFile); michael@0: michael@0: void michael@0: WaitForStoragesToComplete(nsTArray >& aStorages, michael@0: nsIRunnable* aCallback); michael@0: michael@0: void michael@0: AbortLockedFilesForStorage(nsIFileStorage* aFileStorage); michael@0: michael@0: bool michael@0: HasLockedFilesForStorage(nsIFileStorage* aFileStorage); michael@0: michael@0: nsIEventTarget* michael@0: StreamTransportTarget() michael@0: { michael@0: NS_ASSERTION(mStreamTransportTarget, "This should never be null!"); michael@0: return mStreamTransportTarget; michael@0: } michael@0: michael@0: private: michael@0: class LockedFileQueue MOZ_FINAL : public FileHelperListener michael@0: { michael@0: friend class FileService; michael@0: michael@0: public: michael@0: NS_IMETHOD_(MozExternalRefCountType) michael@0: AddRef() MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD_(MozExternalRefCountType) michael@0: Release() MOZ_OVERRIDE; michael@0: michael@0: inline nsresult michael@0: Enqueue(FileHelper* aFileHelper); michael@0: michael@0: virtual void michael@0: OnFileHelperComplete(FileHelper* aFileHelper) MOZ_OVERRIDE; michael@0: michael@0: private: michael@0: inline michael@0: LockedFileQueue(LockedFile* aLockedFile); michael@0: michael@0: nsresult michael@0: ProcessQueue(); michael@0: michael@0: ThreadSafeAutoRefCnt mRefCnt; michael@0: NS_DECL_OWNINGTHREAD michael@0: nsRefPtr mLockedFile; michael@0: nsTArray > mQueue; michael@0: nsRefPtr mCurrentHelper; michael@0: }; michael@0: michael@0: struct DelayedEnqueueInfo michael@0: { michael@0: nsRefPtr mLockedFile; michael@0: nsRefPtr mFileHelper; michael@0: }; michael@0: michael@0: class FileStorageInfo michael@0: { michael@0: friend class FileService; michael@0: michael@0: public: michael@0: inline LockedFileQueue* michael@0: CreateLockedFileQueue(LockedFile* aLockedFile); michael@0: michael@0: inline LockedFileQueue* michael@0: GetLockedFileQueue(LockedFile* aLockedFile); michael@0: michael@0: void michael@0: RemoveLockedFileQueue(LockedFile* aLockedFile); michael@0: michael@0: bool michael@0: HasRunningLockedFiles() michael@0: { michael@0: return !mLockedFileQueues.IsEmpty(); michael@0: } michael@0: michael@0: inline bool michael@0: HasRunningLockedFiles(nsIFileStorage* aFileStorage); michael@0: michael@0: inline DelayedEnqueueInfo* michael@0: CreateDelayedEnqueueInfo(LockedFile* aLockedFile, FileHelper* aFileHelper); michael@0: michael@0: inline void michael@0: CollectRunningAndDelayedLockedFiles( michael@0: nsIFileStorage* aFileStorage, michael@0: nsTArray >& aLockedFiles); michael@0: michael@0: void michael@0: LockFileForReading(const nsAString& aFileName) michael@0: { michael@0: mFilesReading.PutEntry(aFileName); michael@0: } michael@0: michael@0: void michael@0: LockFileForWriting(const nsAString& aFileName) michael@0: { michael@0: mFilesWriting.PutEntry(aFileName); michael@0: } michael@0: michael@0: bool michael@0: IsFileLockedForReading(const nsAString& aFileName) michael@0: { michael@0: return mFilesReading.Contains(aFileName); michael@0: } michael@0: michael@0: bool michael@0: IsFileLockedForWriting(const nsAString& aFileName) michael@0: { michael@0: return mFilesWriting.Contains(aFileName); michael@0: } michael@0: michael@0: private: michael@0: FileStorageInfo() michael@0: { michael@0: } michael@0: michael@0: nsTArray > mLockedFileQueues; michael@0: nsTArray mDelayedEnqueueInfos; michael@0: nsTHashtable mFilesReading; michael@0: nsTHashtable mFilesWriting; michael@0: }; michael@0: michael@0: struct StoragesCompleteCallback michael@0: { michael@0: nsTArray > mStorages; michael@0: nsCOMPtr mCallback; michael@0: }; michael@0: michael@0: FileService(); michael@0: ~FileService(); michael@0: michael@0: nsresult michael@0: Init(); michael@0: michael@0: nsresult michael@0: Cleanup(); michael@0: michael@0: bool michael@0: MaybeFireCallback(StoragesCompleteCallback& aCallback); michael@0: michael@0: nsCOMPtr mStreamTransportTarget; michael@0: nsClassHashtable mFileStorageInfos; michael@0: nsTArray mCompleteCallbacks; michael@0: }; michael@0: michael@0: END_FILE_NAMESPACE michael@0: michael@0: #endif /* mozilla_dom_file_fileservice_h__ */