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 nsDeviceStorage_h michael@0: #define nsDeviceStorage_h michael@0: michael@0: class nsPIDOMWindow; michael@0: #include "mozilla/Attributes.h" michael@0: #include "PCOMContentPermissionRequestChild.h" michael@0: michael@0: #include "DOMRequest.h" michael@0: #include "DOMCursor.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "nsDOMClassInfoID.h" michael@0: #include "nsIClassInfo.h" michael@0: #include "nsIContentPermissionPrompt.h" michael@0: #include "nsIDOMWindow.h" michael@0: #include "nsIURI.h" michael@0: #include "nsInterfaceHashtable.h" michael@0: #include "nsIPrincipal.h" michael@0: #include "nsString.h" michael@0: #include "nsWeakPtr.h" michael@0: #include "nsIDOMEventListener.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsIStringBundle.h" michael@0: #include "mozilla/Mutex.h" michael@0: #include "prtime.h" michael@0: #include "DeviceStorage.h" michael@0: #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h" michael@0: #include "mozilla/StaticPtr.h" michael@0: michael@0: namespace mozilla { michael@0: class ErrorResult; michael@0: } // namespace mozilla michael@0: michael@0: #define POST_ERROR_EVENT_FILE_EXISTS "NoModificationAllowedError" michael@0: #define POST_ERROR_EVENT_FILE_DOES_NOT_EXIST "NotFoundError" michael@0: #define POST_ERROR_EVENT_FILE_NOT_ENUMERABLE "TypeMismatchError" michael@0: #define POST_ERROR_EVENT_PERMISSION_DENIED "SecurityError" michael@0: #define POST_ERROR_EVENT_ILLEGAL_TYPE "TypeMismatchError" michael@0: #define POST_ERROR_EVENT_UNKNOWN "Unknown" michael@0: michael@0: enum DeviceStorageRequestType { michael@0: DEVICE_STORAGE_REQUEST_READ, michael@0: DEVICE_STORAGE_REQUEST_WRITE, michael@0: DEVICE_STORAGE_REQUEST_CREATE, michael@0: DEVICE_STORAGE_REQUEST_DELETE, michael@0: DEVICE_STORAGE_REQUEST_WATCH, michael@0: DEVICE_STORAGE_REQUEST_FREE_SPACE, michael@0: DEVICE_STORAGE_REQUEST_USED_SPACE, michael@0: DEVICE_STORAGE_REQUEST_AVAILABLE, michael@0: DEVICE_STORAGE_REQUEST_STATUS, michael@0: DEVICE_STORAGE_REQUEST_FORMAT, michael@0: DEVICE_STORAGE_REQUEST_MOUNT, michael@0: DEVICE_STORAGE_REQUEST_UNMOUNT, michael@0: DEVICE_STORAGE_REQUEST_CREATEFD michael@0: }; michael@0: michael@0: class DeviceStorageUsedSpaceCache MOZ_FINAL michael@0: { michael@0: public: michael@0: static DeviceStorageUsedSpaceCache* CreateOrGet(); michael@0: michael@0: DeviceStorageUsedSpaceCache(); michael@0: ~DeviceStorageUsedSpaceCache(); michael@0: michael@0: michael@0: class InvalidateRunnable MOZ_FINAL : public nsRunnable michael@0: { michael@0: public: michael@0: InvalidateRunnable(DeviceStorageUsedSpaceCache* aCache, michael@0: const nsAString& aStorageName) michael@0: : mCache(aCache) michael@0: , mStorageName(aStorageName) {} michael@0: michael@0: ~InvalidateRunnable() {} michael@0: michael@0: NS_IMETHOD Run() MOZ_OVERRIDE michael@0: { michael@0: nsRefPtr cacheEntry; michael@0: cacheEntry = mCache->GetCacheEntry(mStorageName); michael@0: if (cacheEntry) { michael@0: cacheEntry->mDirty = true; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: private: michael@0: DeviceStorageUsedSpaceCache* mCache; michael@0: nsString mStorageName; michael@0: }; michael@0: michael@0: void Invalidate(const nsAString& aStorageName) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: MOZ_ASSERT(mIOThread); michael@0: michael@0: nsRefPtr r = new InvalidateRunnable(this, aStorageName); michael@0: mIOThread->Dispatch(r, NS_DISPATCH_NORMAL); michael@0: } michael@0: michael@0: void Dispatch(nsIRunnable* aRunnable) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: MOZ_ASSERT(mIOThread); michael@0: michael@0: mIOThread->Dispatch(aRunnable, NS_DISPATCH_NORMAL); michael@0: } michael@0: michael@0: nsresult AccumUsedSizes(const nsAString& aStorageName, michael@0: uint64_t* aPictureSize, uint64_t* aVideosSize, michael@0: uint64_t* aMusicSize, uint64_t* aTotalSize); michael@0: michael@0: void SetUsedSizes(const nsAString& aStorageName, michael@0: uint64_t aPictureSize, uint64_t aVideosSize, michael@0: uint64_t aMusicSize, uint64_t aTotalSize); michael@0: michael@0: private: michael@0: friend class InvalidateRunnable; michael@0: michael@0: struct CacheEntry michael@0: { michael@0: // Technically, this doesn't need to be threadsafe, but the implementation michael@0: // of the non-thread safe one causes ASSERTS due to the underlying thread michael@0: // associated with a LazyIdleThread changing from time to time. michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceStorageUsedSpaceCache::CacheEntry) michael@0: michael@0: bool mDirty; michael@0: nsString mStorageName; michael@0: int64_t mFreeBytes; michael@0: uint64_t mPicturesUsedSize; michael@0: uint64_t mVideosUsedSize; michael@0: uint64_t mMusicUsedSize; michael@0: uint64_t mTotalUsedSize; michael@0: }; michael@0: already_AddRefed GetCacheEntry(const nsAString& aStorageName); michael@0: michael@0: nsTArray> mCacheEntries; michael@0: michael@0: nsCOMPtr mIOThread; michael@0: michael@0: static mozilla::StaticAutoPtr sDeviceStorageUsedSpaceCache; michael@0: }; michael@0: michael@0: class DeviceStorageTypeChecker MOZ_FINAL michael@0: { michael@0: public: michael@0: static DeviceStorageTypeChecker* CreateOrGet(); michael@0: michael@0: DeviceStorageTypeChecker(); michael@0: ~DeviceStorageTypeChecker(); michael@0: michael@0: void InitFromBundle(nsIStringBundle* aBundle); michael@0: michael@0: bool Check(const nsAString& aType, nsIDOMBlob* aBlob); michael@0: bool Check(const nsAString& aType, nsIFile* aFile); michael@0: void GetTypeFromFile(nsIFile* aFile, nsAString& aType); michael@0: void GetTypeFromFileName(const nsAString& aFileName, nsAString& aType); michael@0: michael@0: static nsresult GetPermissionForType(const nsAString& aType, nsACString& aPermissionResult); michael@0: static nsresult GetAccessForRequest(const DeviceStorageRequestType aRequestType, nsACString& aAccessResult); michael@0: static bool IsVolumeBased(const nsAString& aType); michael@0: michael@0: private: michael@0: nsString mPicturesExtensions; michael@0: nsString mVideosExtensions; michael@0: nsString mMusicExtensions; michael@0: michael@0: static mozilla::StaticAutoPtr sDeviceStorageTypeChecker; michael@0: }; michael@0: michael@0: class ContinueCursorEvent MOZ_FINAL : public nsRunnable michael@0: { michael@0: public: michael@0: ContinueCursorEvent(already_AddRefed aRequest); michael@0: ContinueCursorEvent(mozilla::dom::DOMRequest* aRequest); michael@0: ~ContinueCursorEvent(); michael@0: void Continue(); michael@0: michael@0: NS_IMETHOD Run() MOZ_OVERRIDE; michael@0: private: michael@0: already_AddRefed GetNextFile(); michael@0: nsRefPtr mRequest; michael@0: }; michael@0: michael@0: class nsDOMDeviceStorageCursor MOZ_FINAL michael@0: : public mozilla::dom::DOMCursor michael@0: , public nsIContentPermissionRequest michael@0: , public PCOMContentPermissionRequestChild michael@0: , public mozilla::dom::devicestorage::DeviceStorageRequestChildCallback michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: NS_DECL_NSICONTENTPERMISSIONREQUEST michael@0: NS_FORWARD_NSIDOMDOMCURSOR(mozilla::dom::DOMCursor::) michael@0: michael@0: // DOMCursor michael@0: virtual void Continue(mozilla::ErrorResult& aRv) MOZ_OVERRIDE; michael@0: michael@0: nsDOMDeviceStorageCursor(nsPIDOMWindow* aWindow, michael@0: nsIPrincipal* aPrincipal, michael@0: DeviceStorageFile* aFile, michael@0: PRTime aSince); michael@0: michael@0: michael@0: nsTArray > mFiles; michael@0: bool mOkToCallContinue; michael@0: PRTime mSince; michael@0: michael@0: virtual bool Recv__delete__(const bool& allow, michael@0: const InfallibleTArray& choices) MOZ_OVERRIDE; michael@0: virtual void IPDLRelease() MOZ_OVERRIDE; michael@0: michael@0: void GetStorageType(nsAString & aType); michael@0: michael@0: void RequestComplete() MOZ_OVERRIDE; michael@0: michael@0: private: michael@0: ~nsDOMDeviceStorageCursor(); michael@0: michael@0: nsRefPtr mFile; michael@0: nsCOMPtr mPrincipal; michael@0: }; michael@0: michael@0: //helpers michael@0: JS::Value michael@0: StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString); michael@0: michael@0: JS::Value michael@0: nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile); michael@0: michael@0: JS::Value michael@0: InterfaceToJsval(nsPIDOMWindow* aWindow, nsISupports* aObject, const nsIID* aIID); michael@0: michael@0: #endif