Bug 994190 - 'Modify main-thread IndexedDB to use PBackground', r=khuey.

--HG--
rename : dom/indexedDB/ipc/SerializationHelpers.h => dom/indexedDB/SerializationHelpers.h
rename : dom/indexedDB/ipc/unit/head.js => dom/indexedDB/test/unit/xpcshell-head-child-process.js
rename : dom/indexedDB/test/unit/head.js => dom/indexedDB/test/unit/xpcshell-head-parent-process.js
rename : dom/ipc/Blob.h => dom/ipc/BlobParent.h
rename : dom/ipc/FileDescriptorSetChild.cpp => ipc/glue/FileDescriptorSetChild.cpp
rename : dom/ipc/FileDescriptorSetChild.h => ipc/glue/FileDescriptorSetChild.h
rename : dom/ipc/FileDescriptorSetParent.cpp => ipc/glue/FileDescriptorSetParent.cpp
rename : dom/ipc/FileDescriptorSetParent.h => ipc/glue/FileDescriptorSetParent.h
rename : dom/ipc/PFileDescriptorSet.ipdl => ipc/glue/PFileDescriptorSet.ipdl
This commit is contained in:
Ben Turner 2014-09-13 12:12:19 -04:00
parent 657fde68cc
commit 1a91d40956
231 changed files with 33838 additions and 27055 deletions

View File

@ -33,6 +33,7 @@
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWeakReference.h"
class nsDOMMultipartFile;
class nsIFile;
@ -64,6 +65,7 @@ class DOMFile MOZ_FINAL : public nsIDOMFile
, public nsIXHRSendable
, public nsIMutable
, public nsIJSNativeInitializer
, public nsSupportsWeakReference
{
public:
NS_DECL_NSIDOMBLOB
@ -190,9 +192,9 @@ public:
virtual nsresult GetMozLastModifiedDate(uint64_t* aDate) = 0;
nsresult Slice(int64_t aStart, int64_t aEnd, const nsAString& aContentType,
uint8_t aArgc, nsIDOMBlob **aBlob);
uint8_t aArgc, DOMFileImpl** aBlobImpl);
virtual already_AddRefed<nsIDOMBlob>
virtual already_AddRefed<DOMFileImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType) = 0;
@ -321,7 +323,7 @@ public:
virtual nsresult GetMozLastModifiedDate(uint64_t* aDate) MOZ_OVERRIDE;
virtual already_AddRefed<nsIDOMBlob>
virtual already_AddRefed<DOMFileImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;
@ -464,7 +466,7 @@ public:
virtual nsresult GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
virtual already_AddRefed<nsIDOMBlob>
virtual already_AddRefed<DOMFileImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;
@ -551,7 +553,7 @@ public:
virtual nsresult GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
virtual already_AddRefed<nsIDOMBlob>
virtual already_AddRefed<DOMFileImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;
@ -573,7 +575,7 @@ private:
nsString mContentType;
};
class DOMFileImplFile MOZ_FINAL : public DOMFileImplBase
class DOMFileImplFile : public DOMFileImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -690,6 +692,9 @@ public:
void SetPath(const nsAString& aFullPath);
protected:
virtual ~DOMFileImplFile() {}
private:
// Create slice
DOMFileImplFile(const DOMFileImplFile* aOther, uint64_t aStart,
@ -719,9 +724,7 @@ private:
}
}
~DOMFileImplFile() {}
virtual already_AddRefed<nsIDOMBlob>
virtual already_AddRefed<DOMFileImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;

View File

@ -55,7 +55,7 @@ DOMMultipartFileImpl::GetInternalStream(nsIInputStream** aStream)
return CallQueryInterface(stream, aStream);
}
already_AddRefed<nsIDOMBlob>
already_AddRefed<DOMFileImpl>
DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
{
@ -77,18 +77,17 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
if (skipStart < l) {
uint64_t upperBound = std::min<uint64_t>(l - skipStart, length);
nsCOMPtr<nsIDOMBlob> firstBlob;
rv = blobImpl->Slice(skipStart, skipStart + upperBound,
aContentType, 3,
getter_AddRefs(firstBlob));
nsRefPtr<DOMFileImpl> firstImpl;
rv = blobImpl->Slice(skipStart, skipStart + upperBound, aContentType, 3,
getter_AddRefs(firstImpl));
NS_ENSURE_SUCCESS(rv, nullptr);
// Avoid wrapping a single blob inside an DOMMultipartFileImpl
if (length == upperBound) {
return firstBlob.forget();
return firstImpl.forget();
}
blobImpls.AppendElement(static_cast<DOMFile*>(firstBlob.get())->Impl());
blobImpls.AppendElement(firstImpl);
length -= upperBound;
i++;
break;
@ -105,12 +104,12 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
NS_ENSURE_SUCCESS(rv, nullptr);
if (length < l) {
nsCOMPtr<nsIDOMBlob> lastBlob;
nsRefPtr<DOMFileImpl> lastBlob;
rv = blobImpl->Slice(0, length, aContentType, 3,
getter_AddRefs(lastBlob));
NS_ENSURE_SUCCESS(rv, nullptr);
blobImpls.AppendElement(static_cast<DOMFile*>(lastBlob.get())->Impl());
blobImpls.AppendElement(lastBlob);
} else {
blobImpls.AppendElement(blobImpl);
}
@ -118,9 +117,9 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
}
// we can create our blob now
nsCOMPtr<nsIDOMBlob> blob =
new DOMFile(new DOMMultipartFileImpl(blobImpls, aContentType));
return blob.forget();
nsRefPtr<DOMFileImpl> impl =
new DOMMultipartFileImpl(blobImpls, aContentType);
return impl.forget();
}
/* static */ nsresult

View File

@ -78,7 +78,7 @@ public:
uint32_t aArgc,
JS::Value* aArgv);
virtual already_AddRefed<nsIDOMBlob>
virtual already_AddRefed<DOMFileImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;

View File

@ -147,6 +147,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMFile)
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
NS_INTERFACE_MAP_ENTRY(nsIMutable)
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, IsFile())
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !(IsFile()))
NS_INTERFACE_MAP_END
@ -298,7 +299,10 @@ already_AddRefed<nsIDOMBlob>
DOMFile::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
{
return mImpl->CreateSlice(aStart, aLength, aContentType);
nsRefPtr<DOMFileImpl> impl =
mImpl->CreateSlice(aStart, aLength, aContentType);
nsRefPtr<DOMFile> slice = new DOMFile(impl);
return slice.forget();
}
NS_IMETHODIMP
@ -400,7 +404,17 @@ DOMFile::Slice(int64_t aStart, int64_t aEnd,
nsIDOMBlob **aBlob)
{
MOZ_ASSERT(mImpl);
return mImpl->Slice(aStart, aEnd, aContentType, aArgc, aBlob);
nsRefPtr<DOMFileImpl> impl;
nsresult rv = mImpl->Slice(aStart, aEnd, aContentType, aArgc,
getter_AddRefs(impl));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsRefPtr<DOMFile> blob = new DOMFile(impl);
blob.forget(aBlob);
return NS_OK;
}
NS_IMETHODIMP
@ -460,9 +474,9 @@ DOMFile::IsMemoryFile()
nsresult
DOMFileImpl::Slice(int64_t aStart, int64_t aEnd,
const nsAString& aContentType, uint8_t aArgc,
nsIDOMBlob **aBlob)
DOMFileImpl** aBlobImpl)
{
*aBlob = nullptr;
*aBlobImpl = nullptr;
// Truncate aStart and aEnd so that we stay within this file.
uint64_t thisLength;
@ -475,12 +489,15 @@ DOMFileImpl::Slice(int64_t aStart, int64_t aEnd,
ParseSize((int64_t)thisLength, aStart, aEnd);
// Create the new file
nsCOMPtr<nsIDOMBlob> blob =
nsRefPtr<DOMFileImpl> impl =
CreateSlice((uint64_t)aStart, (uint64_t)(aEnd - aStart), aContentType);
blob.forget(aBlob);
return *aBlob ? NS_OK : NS_ERROR_UNEXPECTED;
if (!impl) {
return NS_ERROR_UNEXPECTED;
}
impl.forget(aBlobImpl);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////
@ -575,7 +592,7 @@ DOMFileImplBase::GetMozLastModifiedDate(uint64_t* aLastModifiedDate)
return NS_OK;
}
already_AddRefed<nsIDOMBlob>
already_AddRefed<DOMFileImpl>
DOMFileImplBase::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
{
@ -724,13 +741,13 @@ DOMFileImplBase::SetMutable(bool aMutable)
////////////////////////////////////////////////////////////////////////////
// DOMFileImplFile implementation
already_AddRefed<nsIDOMBlob>
already_AddRefed<DOMFileImpl>
DOMFileImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
{
nsCOMPtr<nsIDOMBlob> blob =
new DOMFile(new DOMFileImplFile(this, aStart, aLength, aContentType));
return blob.forget();
nsRefPtr<DOMFileImpl> impl =
new DOMFileImplFile(this, aStart, aLength, aContentType);
return impl.forget();
}
nsresult
@ -832,7 +849,8 @@ DOMFileImplFile::GetMozLastModifiedDate(uint64_t* aLastModifiedDate)
const uint32_t sFileStreamFlags =
nsIFileInputStream::CLOSE_ON_EOF |
nsIFileInputStream::REOPEN_ON_REWIND |
nsIFileInputStream::DEFER_OPEN;
nsIFileInputStream::DEFER_OPEN |
nsIFileInputStream::SHARE_DELETE;
nsresult
DOMFileImplFile::GetInternalStream(nsIInputStream** aStream)
@ -857,13 +875,13 @@ DOMFileImplFile::SetPath(const nsAString& aPath)
NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplMemory, DOMFileImpl)
already_AddRefed<nsIDOMBlob>
already_AddRefed<DOMFileImpl>
DOMFileImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
{
nsCOMPtr<nsIDOMBlob> blob =
new DOMFile(new DOMFileImplMemory(this, aStart, aLength, aContentType));
return blob.forget();
nsRefPtr<DOMFileImpl> impl =
new DOMFileImplMemory(this, aStart, aLength, aContentType);
return impl.forget();
}
nsresult
@ -982,17 +1000,17 @@ DOMFileImplMemory::DataOwner::EnsureMemoryReporterRegistered()
NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplTemporaryFileBlob, DOMFileImpl)
already_AddRefed<nsIDOMBlob>
already_AddRefed<DOMFileImpl>
DOMFileImplTemporaryFileBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
{
if (aStart + aLength > mLength)
return nullptr;
nsCOMPtr<nsIDOMBlob> blob =
new DOMFile(new DOMFileImplTemporaryFileBlob(this, aStart + mStartPos,
aLength, aContentType));
return blob.forget();
nsRefPtr<DOMFileImpl> impl =
new DOMFileImplTemporaryFileBlob(this, aStart + mStartPos, aLength,
aContentType);
return impl.forget();
}
nsresult

View File

@ -153,7 +153,6 @@
#include "mozAutoDocUpdate.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/EncodingUtils.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "nsDOMNavigationTiming.h"
#include "nsSMILAnimationController.h"
@ -8517,13 +8516,6 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
}
}
// Check if we have running offline storage transactions
quota::QuotaManager* quotaManager =
win ? quota::QuotaManager::Get() : nullptr;
if (quotaManager && quotaManager->HasOpenTransactions(win)) {
return false;
}
#ifdef MOZ_MEDIA_NAVIGATOR
// Check if we have active GetUserMedia use
if (MediaManager::Exists() && win &&

View File

@ -34,8 +34,8 @@
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/StructuredCloneUtils.h"
#include "mozilla/dom/PBlobChild.h"
#include "mozilla/dom/PBlobParent.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "JavaScriptChild.h"
#include "JavaScriptParent.h"
#include "mozilla/dom/DOMStringList.h"

View File

@ -396,16 +396,15 @@ ArchiveZipFileImpl::Traverse(nsCycleCollectionTraversalCallback &cb)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArchiveReader);
}
already_AddRefed<nsIDOMBlob>
already_AddRefed<mozilla::dom::DOMFileImpl>
ArchiveZipFileImpl::CreateSlice(uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType)
{
nsCOMPtr<nsIDOMBlob> t =
new DOMFile(new ArchiveZipFileImpl(mFilename, mContentType,
aStart, mLength, mCentral,
mArchiveReader));
return t.forget();
nsRefPtr<DOMFileImpl> impl =
new ArchiveZipFileImpl(mFilename, mContentType, aStart, mLength, mCentral,
mArchiveReader);
return impl.forget();
}
NS_IMPL_ISUPPORTS_INHERITED0(ArchiveZipFileImpl, DOMFileImpl)

View File

@ -71,9 +71,9 @@ protected:
MOZ_COUNT_DTOR(ArchiveZipFileImpl);
}
virtual already_AddRefed<nsIDOMBlob> CreateSlice(uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;
virtual already_AddRefed<DOMFileImpl> CreateSlice(uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;
private: // Data
ZipCentral mCentral;

View File

@ -100,6 +100,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla::gfx;
@ -3004,30 +3005,65 @@ nsDOMWindowUtils::AreDialogsEnabled(bool* aResult)
NS_IMETHODIMP
nsDOMWindowUtils::GetFileId(JS::Handle<JS::Value> aFile, JSContext* aCx,
int64_t* aResult)
int64_t* _retval)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
if (!aFile.isPrimitive()) {
JSObject* obj = aFile.toObjectOrNull();
indexedDB::IDBMutableFile* mutableFile = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(IDBMutableFile, obj, mutableFile))) {
*aResult = mutableFile->GetFileId();
return NS_OK;
}
nsISupports* nativeObj =
nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(nativeObj);
if (blob) {
*aResult = blob->GetFileId();
return NS_OK;
}
if (aFile.isPrimitive()) {
*_retval = -1;
return NS_OK;
}
*aResult = -1;
JSObject* obj = aFile.toObjectOrNull();
indexedDB::IDBMutableFile* mutableFile = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(IDBMutableFile, obj, mutableFile))) {
*_retval = mutableFile->GetFileId();
return NS_OK;
}
nsISupports* nativeObj =
nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(nativeObj);
if (blob) {
*_retval = blob->GetFileId();
return NS_OK;
}
*_retval = -1;
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetFilePath(JS::HandleValue aFile, JSContext* aCx,
nsAString& _retval)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
if (aFile.isPrimitive()) {
_retval.Truncate();
return NS_OK;
}
JSObject* obj = aFile.toObjectOrNull();
nsISupports* nativeObj =
nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(nativeObj);
if (file) {
nsString filePath;
nsresult rv = file->GetMozFullPathInternal(filePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
_retval = filePath;
return NS_OK;
}
_retval.Truncate();
return NS_OK;
}

View File

@ -187,7 +187,6 @@
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/MessagePortBinding.h"
#include "mozilla/dom/indexedDB/IDBFactory.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/StructuredCloneTags.h"
@ -1562,12 +1561,6 @@ nsGlobalWindow::FreeInnerObjects()
// Kill all of the workers for this window.
mozilla::dom::workers::CancelWorkersForWindow(this);
// Close all offline storages for this window.
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
if (quotaManager) {
quotaManager->AbortCloseStoragesForWindow(this);
}
ClearAllTimeouts();
if (mIdleTimer) {
@ -10581,9 +10574,11 @@ GetIndexedDBEnabledForAboutURI(nsIURI *aURI)
return flags & nsIAboutModule::ENABLE_INDEXED_DB;
}
indexedDB::IDBFactory*
mozilla::dom::indexedDB::IDBFactory*
nsGlobalWindow::GetIndexedDB(ErrorResult& aError)
{
using mozilla::dom::indexedDB::IDBFactory;
if (!mIndexedDB) {
// If the document has the sandboxed origin flag set
// don't allow access to indexedDB.
@ -10630,8 +10625,7 @@ nsGlobalWindow::GetIndexedDB(ErrorResult& aError)
}
// This may be null if being created from a file.
aError = indexedDB::IDBFactory::Create(this, nullptr,
getter_AddRefs(mIndexedDB));
aError = IDBFactory::CreateForWindow(this, getter_AddRefs(mIndexedDB));
}
return mIndexedDB;

View File

@ -26,6 +26,8 @@
#include "mozilla/unused.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/ipc/UnixSocket.h"
#include "nsContentUtils.h"
#include "nsIObserverService.h"

View File

@ -9,7 +9,6 @@
#include "BluetoothCommon.h"
#include "BluetoothProfileManagerBase.h"
#include "mozilla/dom/ipc/Blob.h"
#include "nsAutoPtr.h"
#include "nsClassHashtable.h"
#include "nsIDOMFile.h"
@ -17,7 +16,13 @@
#include "nsTObserverArray.h"
#include "nsThreadUtils.h"
class nsIDOMBlob;
namespace mozilla {
namespace dom {
class BlobChild;
class BlobParent;
}
namespace ipc {
class UnixSocketConsumer;
}

View File

@ -14,6 +14,7 @@
#include "ObexBase.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"

View File

@ -11,14 +11,20 @@
#include "BluetoothProfileManagerBase.h"
#include "BluetoothSocketObserver.h"
#include "DeviceStorage.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/ipc/UnixSocket.h"
#include "nsCOMArray.h"
class nsIDOMBlob;
class nsIOutputStream;
class nsIInputStream;
class nsIVolumeMountLock;
namespace mozilla {
namespace dom {
class BlobParent;
}
}
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocket;

View File

@ -44,6 +44,7 @@
#include "mozilla/ipc/DBusUtils.h"
#include "mozilla/ipc/RawDBusConnection.h"
#include "mozilla/LazyIdleThread.h"
#include "mozilla/Monitor.h"
#include "mozilla/Mutex.h"
#include "mozilla/NullPtr.h"
#include "mozilla/StaticMutex.h"

View File

@ -14,6 +14,7 @@
#include "ObexBase.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"

View File

@ -11,14 +11,20 @@
#include "BluetoothProfileManagerBase.h"
#include "BluetoothSocketObserver.h"
#include "DeviceStorage.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/ipc/UnixSocket.h"
#include "nsCOMArray.h"
class nsIDOMBlob;
class nsIOutputStream;
class nsIInputStream;
class nsIVolumeMountLock;
namespace mozilla {
namespace dom {
class BlobParent;
}
}
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocket;

View File

@ -10,6 +10,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "BluetoothChild.h"
#include "MainThreadUtils.h"

View File

@ -26,6 +26,8 @@
#include "mozilla/unused.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "nsContentUtils.h"
#include "nsIObserverService.h"
#include "nsISettingsService.h"

View File

@ -9,7 +9,6 @@
#include "BluetoothCommon.h"
#include "BluetoothProfileManagerBase.h"
#include "mozilla/dom/ipc/Blob.h"
#include "nsAutoPtr.h"
#include "nsClassHashtable.h"
#include "nsIDOMFile.h"
@ -17,7 +16,13 @@
#include "nsTObserverArray.h"
#include "nsThreadUtils.h"
class nsIDOMBlob;
namespace mozilla {
namespace dom {
class BlobChild;
class BlobParent;
}
namespace ipc {
class UnixSocketConsumer;
}

View File

@ -14,6 +14,7 @@
#include "ObexBase.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"

View File

@ -11,14 +11,20 @@
#include "BluetoothProfileManagerBase.h"
#include "BluetoothSocketObserver.h"
#include "DeviceStorage.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/ipc/UnixSocket.h"
#include "nsCOMArray.h"
class nsIDOMBlob;
class nsIOutputStream;
class nsIInputStream;
class nsIVolumeMountLock;
namespace mozilla {
namespace dom {
class BlobParent;
}
}
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocket;

View File

@ -14,6 +14,7 @@
#include "ObexBase.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"

View File

@ -11,14 +11,20 @@
#include "BluetoothProfileManagerBase.h"
#include "BluetoothSocketObserver.h"
#include "DeviceStorage.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/ipc/UnixSocket.h"
#include "nsCOMArray.h"
class nsIDOMBlob;
class nsIOutputStream;
class nsIInputStream;
class nsIVolumeMountLock;
namespace mozilla {
namespace dom {
class BlobParent;
}
}
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocket;

View File

@ -7,15 +7,22 @@
#include "DataStoreDB.h"
#include "DataStoreCallbacks.h"
#include "jsapi.h"
#include "mozilla/dom/IDBDatabaseBinding.h"
#include "mozilla/dom/IDBFactoryBinding.h"
#include "mozilla/dom/IDBObjectStoreBinding.h"
#include "mozilla/dom/indexedDB/IDBDatabase.h"
#include "mozilla/dom/indexedDB/IDBEvents.h"
#include "mozilla/dom/indexedDB/IDBFactory.h"
#include "mozilla/dom/indexedDB/IDBIndex.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "mozilla/dom/indexedDB/IDBTransaction.h"
#include "nsComponentManagerUtils.h"
#include "nsContentUtils.h"
#include "nsIDOMEvent.h"
#include "nsIPrincipal.h"
#include "nsIXPConnect.h"
#define DATASTOREDB_VERSION 1
#define DATASTOREDB_NAME "DataStoreDB"
@ -63,7 +70,9 @@ public:
MOZ_ASSERT(version.IsNull());
#endif
return mDatabase->Close();
mDatabase->Close();
return NS_OK;
}
private:
@ -93,7 +102,36 @@ nsresult
DataStoreDB::CreateFactoryIfNeeded()
{
if (!mFactory) {
nsresult rv = IDBFactory::Create(nullptr, getter_AddRefs(mFactory));
nsresult rv;
nsCOMPtr<nsIPrincipal> principal =
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsIXPConnect* xpc = nsContentUtils::XPConnect();
MOZ_ASSERT(xpc);
AutoSafeJSContext cx;
nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
JS::Rooted<JSObject*> global(cx, globalHolder->GetJSObject());
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_UNEXPECTED;
}
// The CreateSandbox call returns a proxy to the actual sandbox object. We
// don't need a proxy here.
global = js::UncheckedUnwrap(global);
JSAutoCompartment ac(cx, global);
rv = IDBFactory::CreateForDatastore(cx, global, getter_AddRefs(mFactory));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -301,11 +339,7 @@ DataStoreDB::Delete()
mTransaction = nullptr;
if (mDatabase) {
rv = mDatabase->Close();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mDatabase->Close();
mDatabase = nullptr;
}

View File

@ -9,8 +9,9 @@
#include "DataStoreCallbacks.h"
#include "DataStoreService.h"
#include "mozilla/dom/DataStoreBinding.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "nsIDOMEvent.h"
namespace mozilla {

View File

@ -22,6 +22,8 @@
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/indexedDB/IDBCursor.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "mozilla/dom/indexedDB/IDBTransaction.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/unused.h"

View File

@ -1,4 +1,4 @@
<!DOCTYPE HTML>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
@ -137,7 +137,7 @@
// Uninstall the apps
function() { uninstallApp(gApps[0]); },
function() { uninstallApp(gApps[1]); },
function() { uninstallApp(gApps[1]); }
];
function runTest() {

View File

@ -8,7 +8,7 @@
#include "DeviceStorageFileDescriptor.h"
#include "nsDeviceStorage.h"
#include "nsDOMFile.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/dom/ipc/BlobChild.h"
namespace mozilla {
namespace dom {

View File

@ -8,7 +8,7 @@
#include "nsIMIMEService.h"
#include "nsCExternalHandlerService.h"
#include "mozilla/unused.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "ContentParent.h"
#include "nsProxyRelease.h"
#include "AppProcessChecker.h"

View File

@ -16,7 +16,7 @@
#include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/PBrowserChild.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/Promise.h"

View File

@ -8,7 +8,9 @@
#include "FileHelper.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/ipc/InputStreamParams.h"
#include "MutableFile.h"
#include "nsDebug.h"
#include "nsError.h"
@ -16,6 +18,10 @@
#include "nsISeekableStream.h"
#include "nsThreadUtils.h"
#ifdef DEBUG
#include "nsXULAppAPI.h"
#endif
namespace mozilla {
namespace dom {
@ -127,7 +133,8 @@ FileInputStreamWrapper::FileInputStreamWrapper(nsISupports* aFileStream,
NS_IMPL_ISUPPORTS_INHERITED(FileInputStreamWrapper,
FileStreamWrapper,
nsIInputStream)
nsIInputStream,
nsIIPCSerializableInputStream)
NS_IMETHODIMP
FileInputStreamWrapper::Close()
@ -230,6 +237,26 @@ FileInputStreamWrapper::IsNonBlocking(bool* _retval)
return NS_OK;
}
void
FileInputStreamWrapper::Serialize(InputStreamParams& aParams,
FileDescriptorArray& /* aFDs */)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIInputStream> thisStream = do_QueryObject(this);
aParams = mozilla::ipc::SameProcessInputStreamParams(
reinterpret_cast<intptr_t>(thisStream.forget().take()));
}
bool
FileInputStreamWrapper::Deserialize(const InputStreamParams& /* aParams */,
const FileDescriptorArray& /* aFDs */)
{
MOZ_CRASH("Should never get here!");
}
FileOutputStreamWrapper::FileOutputStreamWrapper(nsISupports* aFileStream,
FileHelper* aFileHelper,
uint64_t aOffset,

View File

@ -11,8 +11,13 @@
#include "nsCOMPtr.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIIPCSerializableInputStream.h"
namespace mozilla {
namespace ipc {
class InputStreamParams;
} // namespace ipc
namespace dom {
class FileHelper;
@ -46,11 +51,15 @@ protected:
};
class FileInputStreamWrapper : public FileStreamWrapper,
public nsIInputStream
public nsIInputStream,
public nsIIPCSerializableInputStream
{
typedef mozilla::ipc::InputStreamParams InputStreamParams;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
FileInputStreamWrapper(nsISupports* aFileStream,
FileHelper* aFileHelper,

View File

@ -28,6 +28,8 @@ UNIFIED_SOURCES += [
FAIL_ON_WARNINGS = True
include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [
'../base',
]

View File

@ -13,6 +13,8 @@
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "nsDOMFile.h"
#include "nsIFile.h"
#include "nsNetUtil.h"

View File

@ -13,6 +13,7 @@
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PContent.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/unused.h"
#include "nsDOMFile.h"

View File

@ -10,13 +10,13 @@
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/FileSystemRequestParent.h"
#include "mozilla/dom/PFileSystemRequestChild.h"
#include "mozilla/dom/ipc/Blob.h"
class nsIDOMFile;
namespace mozilla {
namespace dom {
class BlobParent;
class FileSystemBase;
class FileSystemParams;
class Promise;

View File

@ -11,6 +11,8 @@
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "nsDOMFile.h"
#include "nsIFile.h"
#include "nsStringGlue.h"

View File

@ -10,6 +10,8 @@
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "nsDOMFile.h"
#include "nsIFile.h"
#include "nsStringGlue.h"

File diff suppressed because it is too large Load Diff

627
dom/indexedDB/ActorsChild.h Normal file
View File

@ -0,0 +1,627 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_indexeddb_actorschild_h__
#define mozilla_dom_indexeddb_actorschild_h__
#include "js/RootingAPI.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBCursorChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBFactoryRequestChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBRequestChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBTransactionChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBVersionChangeTransactionChild.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"
class nsIEventTarget;
struct PRThread;
namespace mozilla {
namespace ipc {
class BackgroundChildImpl;
} // namespace ipc
namespace dom {
namespace indexedDB {
class FileInfo;
class IDBCursor;
class IDBDatabase;
class IDBFactory;
class IDBMutableFile;
class IDBOpenDBRequest;
class IDBRequest;
class IDBTransaction;
class Key;
class PBackgroundIDBFileChild;
class PermissionRequestChild;
class PermissionRequestParent;
class SerializedStructuredCloneReadInfo;
class BackgroundFactoryChild MOZ_FINAL
: public PBackgroundIDBFactoryChild
{
friend class mozilla::ipc::BackgroundChildImpl;
friend class IDBFactory;
IDBFactory* mFactory;
#ifdef DEBUG
nsCOMPtr<nsIEventTarget> mOwningThread;
#endif
public:
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
IDBFactory*
GetDOMObject() const
{
AssertIsOnOwningThread();
return mFactory;
}
private:
// Only created by IDBFactory.
BackgroundFactoryChild(IDBFactory* aFactory);
// Only destroyed by mozilla::ipc::BackgroundChildImpl.
~BackgroundFactoryChild();
void
SendDeleteMeInternal();
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual PBackgroundIDBFactoryRequestChild*
AllocPBackgroundIDBFactoryRequestChild(const FactoryRequestParams& aParams)
MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBFactoryRequestChild(
PBackgroundIDBFactoryRequestChild* aActor)
MOZ_OVERRIDE;
virtual PBackgroundIDBDatabaseChild*
AllocPBackgroundIDBDatabaseChild(const DatabaseSpec& aSpec,
PBackgroundIDBFactoryRequestChild* aRequest)
MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBDatabaseChild(PBackgroundIDBDatabaseChild* aActor)
MOZ_OVERRIDE;
bool
SendDeleteMe() MOZ_DELETE;
};
class BackgroundDatabaseChild;
class BackgroundRequestChildBase
{
protected:
nsRefPtr<IDBRequest> mRequest;
private:
bool mActorDestroyed;
public:
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
IDBRequest*
GetDOMObject() const
{
AssertIsOnOwningThread();
return mRequest;
}
bool
IsActorDestroyed() const
{
AssertIsOnOwningThread();
return mActorDestroyed;
}
protected:
BackgroundRequestChildBase(IDBRequest* aRequest);
virtual
~BackgroundRequestChildBase();
void
NoteActorDestroyed();
};
class BackgroundFactoryRequestChild MOZ_FINAL
: public BackgroundRequestChildBase
, public PBackgroundIDBFactoryRequestChild
{
typedef mozilla::dom::quota::PersistenceType PersistenceType;
friend class IDBFactory;
friend class BackgroundFactoryChild;
friend class BackgroundDatabaseChild;
friend class PermissionRequestChild;
friend class PermissionRequestParent;
nsRefPtr<IDBFactory> mFactory;
const uint64_t mRequestedVersion;
const PersistenceType mPersistenceType;
const bool mIsDeleteOp;
public:
IDBOpenDBRequest*
GetOpenDBRequest() const;
private:
// Only created by IDBFactory.
BackgroundFactoryRequestChild(IDBFactory* aFactory,
IDBOpenDBRequest* aOpenRequest,
bool aIsDeleteOp,
uint64_t aRequestedVersion,
PersistenceType aPersistenceType);
// Only destroyed by BackgroundFactoryChild.
~BackgroundFactoryRequestChild();
bool
HandleResponse(nsresult aResponse);
bool
HandleResponse(const OpenDatabaseRequestResponse& aResponse);
bool
HandleResponse(const DeleteDatabaseRequestResponse& aResponse);
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool
Recv__delete__(const FactoryRequestResponse& aResponse) MOZ_OVERRIDE;
virtual bool
RecvPermissionChallenge(const PrincipalInfo& aPrincipalInfo) MOZ_OVERRIDE;
virtual bool
RecvBlocked(const uint64_t& aCurrentVersion) MOZ_OVERRIDE;
};
class BackgroundDatabaseChild MOZ_FINAL
: public PBackgroundIDBDatabaseChild
{
typedef mozilla::dom::quota::PersistenceType PersistenceType;
friend class BackgroundFactoryChild;
friend class BackgroundFactoryRequestChild;
friend class IDBDatabase;
nsAutoPtr<DatabaseSpec> mSpec;
nsRefPtr<IDBDatabase> mTemporaryStrongDatabase;
BackgroundFactoryRequestChild* mOpenRequestActor;
IDBDatabase* mDatabase;
PersistenceType mPersistenceType;
public:
void
AssertIsOnOwningThread() const
{
static_cast<BackgroundFactoryChild*>(Manager())->AssertIsOnOwningThread();
}
const DatabaseSpec*
Spec() const
{
AssertIsOnOwningThread();
return mSpec;
}
IDBDatabase*
GetDOMObject() const
{
AssertIsOnOwningThread();
return mDatabase;
}
private:
// Only constructed by BackgroundFactoryChild.
BackgroundDatabaseChild(const DatabaseSpec& aSpec,
BackgroundFactoryRequestChild* aOpenRequest);
// Only destroyed by BackgroundFactoryChild.
~BackgroundDatabaseChild();
void
SendDeleteMeInternal();
void
EnsureDOMObject();
void
ReleaseDOMObject();
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual PBackgroundIDBDatabaseFileChild*
AllocPBackgroundIDBDatabaseFileChild(
const BlobOrInputStream& aBlobOrInputStream)
MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBDatabaseFileChild(
PBackgroundIDBDatabaseFileChild* aActor)
MOZ_OVERRIDE;
virtual PBackgroundIDBTransactionChild*
AllocPBackgroundIDBTransactionChild(
const nsTArray<nsString>& aObjectStoreNames,
const Mode& aMode)
MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBTransactionChild(PBackgroundIDBTransactionChild* aActor)
MOZ_OVERRIDE;
virtual PBackgroundIDBVersionChangeTransactionChild*
AllocPBackgroundIDBVersionChangeTransactionChild(
const uint64_t& aCurrentVersion,
const uint64_t& aRequestedVersion,
const int64_t& aNextObjectStoreId,
const int64_t& aNextIndexId)
MOZ_OVERRIDE;
virtual bool
RecvPBackgroundIDBVersionChangeTransactionConstructor(
PBackgroundIDBVersionChangeTransactionChild* aActor,
const uint64_t& aCurrentVersion,
const uint64_t& aRequestedVersion,
const int64_t& aNextObjectStoreId,
const int64_t& aNextIndexId)
MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBVersionChangeTransactionChild(
PBackgroundIDBVersionChangeTransactionChild* aActor)
MOZ_OVERRIDE;
virtual bool
RecvVersionChange(const uint64_t& aOldVersion,
const NullableVersion& aNewVersion)
MOZ_OVERRIDE;
virtual bool
RecvInvalidate() MOZ_OVERRIDE;
bool
SendDeleteMe() MOZ_DELETE;
};
class BackgroundVersionChangeTransactionChild;
class BackgroundTransactionBase
{
friend class BackgroundVersionChangeTransactionChild;
// mTemporaryStrongTransaction is strong and is only valid until the end of
// NoteComplete() member function or until the NoteActorDestroyed() member
// function is called.
nsRefPtr<IDBTransaction> mTemporaryStrongTransaction;
protected:
// mTransaction is weak and is valid until the NoteActorDestroyed() member
// function is called.
IDBTransaction* mTransaction;
public:
#ifdef DEBUG
virtual void
AssertIsOnOwningThread() const = 0;
#else
void
AssertIsOnOwningThread() const
{ }
#endif
IDBTransaction*
GetDOMObject() const
{
AssertIsOnOwningThread();
return mTransaction;
}
protected:
BackgroundTransactionBase();
BackgroundTransactionBase(IDBTransaction* aTransaction);
virtual
~BackgroundTransactionBase();
void
NoteActorDestroyed();
void
NoteComplete();
private:
// Only called by BackgroundVersionChangeTransactionChild.
void
SetDOMTransaction(IDBTransaction* aDOMObject);
};
class BackgroundTransactionChild MOZ_FINAL
: public BackgroundTransactionBase
, public PBackgroundIDBTransactionChild
{
friend class BackgroundDatabaseChild;
friend class IDBDatabase;
public:
#ifdef DEBUG
virtual void
AssertIsOnOwningThread() const MOZ_OVERRIDE;
#endif
void
SendDeleteMeInternal();
private:
// Only created by IDBDatabase.
BackgroundTransactionChild(IDBTransaction* aTransaction);
// Only destroyed by BackgroundDatabaseChild.
~BackgroundTransactionChild();
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
bool
RecvComplete(const nsresult& aResult) MOZ_OVERRIDE;
virtual PBackgroundIDBRequestChild*
AllocPBackgroundIDBRequestChild(const RequestParams& aParams) MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBRequestChild(PBackgroundIDBRequestChild* aActor)
MOZ_OVERRIDE;
virtual PBackgroundIDBCursorChild*
AllocPBackgroundIDBCursorChild(const OpenCursorParams& aParams) MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild* aActor)
MOZ_OVERRIDE;
bool
SendDeleteMe() MOZ_DELETE;
};
class BackgroundVersionChangeTransactionChild MOZ_FINAL
: public BackgroundTransactionBase
, public PBackgroundIDBVersionChangeTransactionChild
{
friend class BackgroundDatabaseChild;
IDBOpenDBRequest* mOpenDBRequest;
public:
#ifdef DEBUG
virtual void
AssertIsOnOwningThread() const MOZ_OVERRIDE;
#endif
void
SendDeleteMeInternal();
private:
// Only created by BackgroundDatabaseChild.
BackgroundVersionChangeTransactionChild(IDBOpenDBRequest* aOpenDBRequest);
// Only destroyed by BackgroundDatabaseChild.
~BackgroundVersionChangeTransactionChild();
// Only called by BackgroundDatabaseChild.
void
SetDOMTransaction(IDBTransaction* aDOMObject)
{
BackgroundTransactionBase::SetDOMTransaction(aDOMObject);
}
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
bool
RecvComplete(const nsresult& aResult) MOZ_OVERRIDE;
virtual PBackgroundIDBRequestChild*
AllocPBackgroundIDBRequestChild(const RequestParams& aParams) MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBRequestChild(PBackgroundIDBRequestChild* aActor)
MOZ_OVERRIDE;
virtual PBackgroundIDBCursorChild*
AllocPBackgroundIDBCursorChild(const OpenCursorParams& aParams) MOZ_OVERRIDE;
virtual bool
DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild* aActor)
MOZ_OVERRIDE;
bool
SendDeleteMe() MOZ_DELETE;
};
class BackgroundRequestChild MOZ_FINAL
: public BackgroundRequestChildBase
, public PBackgroundIDBRequestChild
{
friend class BackgroundTransactionChild;
friend class BackgroundVersionChangeTransactionChild;
nsRefPtr<IDBTransaction> mTransaction;
nsTArray<nsRefPtr<FileInfo>> mFileInfos;
public:
BackgroundRequestChild(IDBRequest* aRequest);
void
HoldFileInfosUntilComplete(nsTArray<nsRefPtr<FileInfo>>& aFileInfos);
private:
// Only destroyed by BackgroundTransactionChild or
// BackgroundVersionChangeTransactionChild.
~BackgroundRequestChild();
void
MaybeFinishTransactionEarly();
bool
HandleResponse(nsresult aResponse);
bool
HandleResponse(const Key& aResponse);
bool
HandleResponse(const nsTArray<Key>& aResponse);
bool
HandleResponse(const SerializedStructuredCloneReadInfo& aResponse);
bool
HandleResponse(const nsTArray<SerializedStructuredCloneReadInfo>& aResponse);
bool
HandleResponse(JS::Handle<JS::Value> aResponse);
bool
HandleResponse(uint64_t aResponse);
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool
Recv__delete__(const RequestResponse& aResponse) MOZ_OVERRIDE;
};
class BackgroundCursorChild MOZ_FINAL
: public PBackgroundIDBCursorChild
{
friend class BackgroundTransactionChild;
friend class BackgroundVersionChangeTransactionChild;
class DelayedDeleteRunnable;
IDBRequest* mRequest;
IDBTransaction* mTransaction;
IDBObjectStore* mObjectStore;
IDBIndex* mIndex;
IDBCursor* mCursor;
// These are only set while a request is in progress.
nsRefPtr<IDBRequest> mStrongRequest;
nsRefPtr<IDBCursor> mStrongCursor;
Direction mDirection;
#ifdef DEBUG
PRThread* mOwningThread;
#endif
public:
BackgroundCursorChild(IDBRequest* aRequest,
IDBObjectStore* aObjectStore,
Direction aDirection);
BackgroundCursorChild(IDBRequest* aRequest,
IDBIndex* aIndex,
Direction aDirection);
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
void
SendContinueInternal(const CursorRequestParams& aParams);
void
SendDeleteMeInternal();
private:
// Only destroyed by BackgroundTransactionChild or
// BackgroundVersionChangeTransactionChild.
~BackgroundCursorChild();
void
HandleResponse(nsresult aResponse);
void
HandleResponse(const void_t& aResponse);
void
HandleResponse(const ObjectStoreCursorResponse& aResponse);
void
HandleResponse(const ObjectStoreKeyCursorResponse& aResponse);
void
HandleResponse(const IndexCursorResponse& aResponse);
void
HandleResponse(const IndexKeyCursorResponse& aResponse);
// IPDL methods are only called by IPDL.
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool
RecvResponse(const CursorResponse& aResponse) MOZ_OVERRIDE;
// Force callers to use SendContinueInternal.
bool
SendContinue(const CursorRequestParams& aParams) MOZ_DELETE;
bool
SendDeleteMe() MOZ_DELETE;
};
// XXX This doesn't belong here. However, we're not yet porting MutableFile
// stuff to PBackground so this is necessary for the time being.
void
DispatchMutableFileResult(IDBRequest* aRequest,
nsresult aResultCode,
IDBMutableFile* aMutableFile);
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_actorschild_h__

17020
dom/indexedDB/ActorsParent.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_indexeddb_actorsparent_h__
#define mozilla_dom_indexeddb_actorsparent_h__
template <class> struct already_AddRefed;
class nsCString;
class nsIPrincipal;
class nsPIDOMWindow;
namespace mozilla {
namespace ipc {
class PBackgroundParent;
} // namespace ipc
namespace dom {
class TabParent;
namespace quota {
class Client;
} // namespace quota
namespace indexedDB {
class OptionalWindowId;
class PBackgroundIDBFactoryParent;
class PIndexedDBPermissionRequestParent;
PBackgroundIDBFactoryParent*
AllocPBackgroundIDBFactoryParent(mozilla::ipc::PBackgroundParent* aManager,
const OptionalWindowId& aOptionalWindowId);
bool
RecvPBackgroundIDBFactoryConstructor(mozilla::ipc::PBackgroundParent* aManager,
PBackgroundIDBFactoryParent* aActor,
const OptionalWindowId& aOptionalWindowId);
bool
DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor);
PIndexedDBPermissionRequestParent*
AllocPIndexedDBPermissionRequestParent(nsPIDOMWindow* aWindow,
nsIPrincipal* aPrincipal);
bool
RecvPIndexedDBPermissionRequestConstructor(
PIndexedDBPermissionRequestParent* aActor);
bool
DeallocPIndexedDBPermissionRequestParent(
PIndexedDBPermissionRequestParent* aActor);
already_AddRefed<mozilla::dom::quota::Client>
CreateQuotaClient();
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_actorsparent_h__

View File

@ -1,710 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "AsyncConnectionHelper.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/storage.h"
#include "nsComponentManagerUtils.h"
#include "nsContentUtils.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
#include "nsWrapperCacheInlines.h"
#include "IDBEvents.h"
#include "IDBTransaction.h"
#include "IndexedDatabaseManager.h"
#include "ProfilerHelpers.h"
#include "ReportInternalError.h"
#include "TransactionThreadPool.h"
#include "ipc/IndexedDBChild.h"
#include "ipc/IndexedDBParent.h"
using namespace mozilla;
USING_INDEXEDDB_NAMESPACE
using mozilla::dom::quota::QuotaManager;
namespace {
IDBTransaction* gCurrentTransaction = nullptr;
const uint32_t kProgressHandlerGranularity = 1000;
class MOZ_STACK_CLASS TransactionPoolEventTarget : public StackBasedEventTarget
{
public:
NS_DECL_NSIEVENTTARGET
explicit TransactionPoolEventTarget(IDBTransaction* aTransaction)
: mTransaction(aTransaction)
{ }
private:
IDBTransaction* mTransaction;
};
// This inline is just so that we always clear aBuffers appropriately even if
// something fails.
inline
nsresult
ConvertCloneReadInfosToArrayInternal(
JSContext* aCx,
nsTArray<StructuredCloneReadInfo>& aReadInfos,
JS::MutableHandle<JS::Value> aResult)
{
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
if (!array) {
IDB_WARNING("Failed to make array!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
if (!aReadInfos.IsEmpty()) {
if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) {
IDB_WARNING("Failed to set array length!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
for (uint32_t index = 0, count = aReadInfos.Length(); index < count;
index++) {
StructuredCloneReadInfo& readInfo = aReadInfos[index];
JS::Rooted<JS::Value> val(aCx);
if (!IDBObjectStore::DeserializeValue(aCx, readInfo, &val)) {
NS_WARNING("Failed to decode!");
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
if (!JS_SetElement(aCx, array, index, val)) {
IDB_WARNING("Failed to set array element!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
}
aResult.setObject(*array);
return NS_OK;
}
} // anonymous namespace
HelperBase::~HelperBase()
{
if (!NS_IsMainThread()) {
IDBRequest* request;
mRequest.forget(&request);
if (request) {
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
if (mainThread) {
NS_ProxyRelease(mainThread, static_cast<EventTarget*>(request));
}
}
}
}
nsresult
HelperBase::WrapNative(JSContext* aCx,
nsISupports* aNative,
JS::MutableHandle<JS::Value> aResult)
{
NS_ASSERTION(aCx, "Null context!");
NS_ASSERTION(aNative, "Null pointer!");
NS_ASSERTION(aResult.address(), "Null pointer!");
NS_ASSERTION(mRequest, "Null request!");
nsresult rv = nsContentUtils::WrapNative(aCx, aNative, aResult);
IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return NS_OK;
}
void
HelperBase::ReleaseMainThreadObjects()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mRequest = nullptr;
}
AsyncConnectionHelper::AsyncConnectionHelper(IDBDatabase* aDatabase,
IDBRequest* aRequest)
: HelperBase(aRequest),
mDatabase(aDatabase),
mResultCode(NS_OK),
mDispatched(false)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
}
AsyncConnectionHelper::AsyncConnectionHelper(IDBTransaction* aTransaction,
IDBRequest* aRequest)
: HelperBase(aRequest),
mDatabase(aTransaction->mDatabase),
mTransaction(aTransaction),
mResultCode(NS_OK),
mDispatched(false)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
}
AsyncConnectionHelper::~AsyncConnectionHelper()
{
if (!NS_IsMainThread()) {
IDBDatabase* database;
mDatabase.forget(&database);
IDBTransaction* transaction;
mTransaction.forget(&transaction);
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
if (mainThread) {
if (database) {
NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(database));
}
if (transaction) {
NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(transaction));
}
}
}
NS_ASSERTION(!mOldProgressHandler, "Should not have anything here!");
}
NS_IMPL_ISUPPORTS(AsyncConnectionHelper, nsIRunnable,
mozIStorageProgressHandler)
NS_IMETHODIMP
AsyncConnectionHelper::Run()
{
if (NS_IsMainThread()) {
PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "Run",
js::ProfileEntry::Category::STORAGE);
if (mTransaction &&
mTransaction->IsAborted()) {
// Always fire a "error" event with ABORT_ERR if the transaction was
// aborted, even if the request succeeded or failed with another error.
mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
}
IDBTransaction* oldTransaction = gCurrentTransaction;
gCurrentTransaction = mTransaction;
ChildProcessSendResult sendResult =
IndexedDatabaseManager::IsMainProcess() ?
MaybeSendResponseToChildProcess(mResultCode) :
Success_NotSent;
switch (sendResult) {
case Success_Sent: {
if (mRequest) {
mRequest->NotifyHelperSentResultsToChildProcess(NS_OK);
}
break;
}
case Success_NotSent: {
if (mRequest) {
nsresult rv = mRequest->NotifyHelperCompleted(this);
if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) {
mResultCode = rv;
}
IDB_PROFILER_MARK("IndexedDB Request %llu: Running main thread "
"response (rv = %lu)",
"IDBRequest[%llu] MT Done",
mRequest->GetSerialNumber(), mResultCode);
}
// Call OnError if the database had an error or if the OnSuccess
// handler has an error.
if (NS_FAILED(mResultCode) ||
NS_FAILED((mResultCode = OnSuccess()))) {
OnError();
}
break;
}
case Success_ActorDisconnected: {
// Nothing needs to be done here.
break;
}
case Error: {
IDB_WARNING("MaybeSendResultsToChildProcess failed!");
mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
if (mRequest) {
mRequest->NotifyHelperSentResultsToChildProcess(mResultCode);
}
break;
}
default:
MOZ_CRASH("Unknown value for ChildProcessSendResult!");
}
NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!");
gCurrentTransaction = oldTransaction;
if (mDispatched && mTransaction) {
mTransaction->OnRequestFinished();
}
ReleaseMainThreadObjects();
NS_ASSERTION(!(mDatabase || mTransaction || mRequest), "Subclass didn't "
"call AsyncConnectionHelper::ReleaseMainThreadObjects!");
return NS_OK;
}
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("AsyncConnectionHelper", "Run",
js::ProfileEntry::Category::STORAGE);
IDB_PROFILER_MARK_IF(mRequest,
"IndexedDB Request %llu: Beginning database work",
"IDBRequest[%llu] DT Start",
mRequest->GetSerialNumber());
nsresult rv = NS_OK;
nsCOMPtr<mozIStorageConnection> connection;
if (mTransaction) {
rv = mTransaction->GetOrCreateConnection(getter_AddRefs(connection));
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(connection, "This should never be null!");
}
}
bool setProgressHandler = false;
if (connection) {
rv = connection->SetProgressHandler(kProgressHandlerGranularity, this,
getter_AddRefs(mOldProgressHandler));
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "SetProgressHandler failed!");
if (NS_SUCCEEDED(rv)) {
setProgressHandler = true;
}
}
if (NS_SUCCEEDED(rv)) {
bool hasSavepoint = false;
if (mDatabase) {
QuotaManager::SetCurrentWindow(mDatabase->GetOwner());
// Make the first savepoint.
if (mTransaction) {
if (!(hasSavepoint = mTransaction->StartSavepoint())) {
NS_WARNING("Failed to make savepoint!");
}
}
}
mResultCode = DoDatabaseWork(connection);
if (mDatabase) {
// Release or roll back the savepoint depending on the error code.
if (hasSavepoint) {
NS_ASSERTION(mTransaction, "Huh?!");
if (NS_SUCCEEDED(mResultCode)) {
mTransaction->ReleaseSavepoint();
}
else {
mTransaction->RollbackSavepoint();
}
}
// Don't unset this until we're sure that all SQLite activity has
// completed!
QuotaManager::SetCurrentWindow(nullptr);
}
}
else {
// NS_ERROR_NOT_AVAILABLE is our special code for "database is invalidated"
// and we should fail with RECOVERABLE_ERR.
if (rv == NS_ERROR_NOT_AVAILABLE) {
mResultCode = NS_ERROR_DOM_INDEXEDDB_RECOVERABLE_ERR;
}
else {
IDB_REPORT_INTERNAL_ERR();
mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
if (setProgressHandler) {
nsCOMPtr<mozIStorageProgressHandler> handler;
rv = connection->RemoveProgressHandler(getter_AddRefs(handler));
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "RemoveProgressHandler failed!");
#ifdef DEBUG
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(SameCOMIdentity(handler, static_cast<nsIRunnable*>(this)),
"Mismatch!");
}
#endif
}
IDB_PROFILER_MARK_IF(mRequest,
"IndexedDB Request %llu: Finished database work "
"(rv = %lu)",
"IDBRequest[%llu] DT Done", mRequest->GetSerialNumber(),
mResultCode);
return NS_DispatchToMainThread(this);
}
NS_IMETHODIMP
AsyncConnectionHelper::OnProgress(mozIStorageConnection* aConnection,
bool* _retval)
{
if (mDatabase && mDatabase->IsInvalidated()) {
// Someone is trying to delete the database file. Exit lightningfast!
*_retval = true;
return NS_OK;
}
if (mOldProgressHandler) {
return mOldProgressHandler->OnProgress(aConnection, _retval);
}
*_retval = false;
return NS_OK;
}
nsresult
AsyncConnectionHelper::Dispatch(nsIEventTarget* aTarget)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsresult rv = Init();
if (NS_FAILED(rv)) {
return rv;
}
rv = aTarget->Dispatch(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
if (mTransaction) {
mTransaction->OnNewRequest();
}
mDispatched = true;
return NS_OK;
}
nsresult
AsyncConnectionHelper::DispatchToTransactionPool()
{
NS_ASSERTION(mTransaction, "Only ok to call this with a transaction!");
TransactionPoolEventTarget target(mTransaction);
return Dispatch(&target);
}
// static
void
AsyncConnectionHelper::SetCurrentTransaction(IDBTransaction* aTransaction)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!aTransaction || !gCurrentTransaction,
"Stepping on another transaction!");
gCurrentTransaction = aTransaction;
}
// static
IDBTransaction*
AsyncConnectionHelper::GetCurrentTransaction()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return gCurrentTransaction;
}
nsresult
AsyncConnectionHelper::Init()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return NS_OK;
}
already_AddRefed<nsIDOMEvent>
AsyncConnectionHelper::CreateSuccessEvent(mozilla::dom::EventTarget* aOwner)
{
return CreateGenericEvent(mRequest, NS_LITERAL_STRING(SUCCESS_EVT_STR),
eDoesNotBubble, eNotCancelable);
}
nsresult
AsyncConnectionHelper::OnSuccess()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(mRequest, "Null request!");
PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "OnSuccess",
js::ProfileEntry::Category::STORAGE);
nsRefPtr<nsIDOMEvent> event = CreateSuccessEvent(mRequest);
if (!event) {
IDB_WARNING("Failed to create event!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
bool dummy;
nsresult rv = mRequest->DispatchEvent(event, &dummy);
IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
WidgetEvent* internalEvent = event->GetInternalNSEvent();
NS_ASSERTION(internalEvent, "This should never be null!");
NS_ASSERTION(!mTransaction ||
mTransaction->IsOpen() ||
mTransaction->IsAborted(),
"How else can this be closed?!");
if (internalEvent->mFlags.mExceptionHasBeenRisen &&
mTransaction &&
mTransaction->IsOpen()) {
rv = mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
void
AsyncConnectionHelper::OnError()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(mRequest, "Null request!");
PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "OnError",
js::ProfileEntry::Category::STORAGE);
// Make an error event and fire it at the target.
nsRefPtr<nsIDOMEvent> event =
CreateGenericEvent(mRequest, NS_LITERAL_STRING(ERROR_EVT_STR), eDoesBubble,
eCancelable);
if (!event) {
NS_ERROR("Failed to create event!");
return;
}
bool doDefault;
nsresult rv = mRequest->DispatchEvent(event, &doDefault);
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(!mTransaction ||
mTransaction->IsOpen() ||
mTransaction->IsAborted(),
"How else can this be closed?!");
WidgetEvent* internalEvent = event->GetInternalNSEvent();
NS_ASSERTION(internalEvent, "This should never be null!");
if (internalEvent->mFlags.mExceptionHasBeenRisen &&
mTransaction &&
mTransaction->IsOpen() &&
NS_FAILED(mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR))) {
NS_WARNING("Failed to abort transaction!");
}
if (doDefault &&
mTransaction &&
mTransaction->IsOpen() &&
NS_FAILED(mTransaction->Abort(mRequest))) {
NS_WARNING("Failed to abort transaction!");
}
}
else {
NS_WARNING("DispatchEvent failed!");
}
}
nsresult
AsyncConnectionHelper::GetSuccessResult(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
aVal.setUndefined();
return NS_OK;
}
void
AsyncConnectionHelper::ReleaseMainThreadObjects()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mDatabase = nullptr;
mTransaction = nullptr;
HelperBase::ReleaseMainThreadObjects();
}
AsyncConnectionHelper::ChildProcessSendResult
AsyncConnectionHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
// If there's no request, there could never have been an actor, and so there
// is nothing to do.
if (!mRequest) {
return Success_NotSent;
}
IDBTransaction* trans = GetCurrentTransaction();
// We may not have a transaction, e.g. for deleteDatabase
if (!trans) {
return Success_NotSent;
}
// Are we shutting down the child?
IndexedDBDatabaseParent* dbActor = trans->Database()->GetActorParent();
if (dbActor && dbActor->IsDisconnected()) {
return Success_ActorDisconnected;
}
IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
if (!actor) {
return Success_NotSent;
}
IDB_PROFILER_MARK("IndexedDB Request %llu: Sending response to child "
"process (rv = %lu)",
"IDBRequest[%llu] MT Done",
mRequest->GetSerialNumber(), aResultCode);
return SendResponseToChildProcess(aResultCode);
}
nsresult
AsyncConnectionHelper::OnParentProcessRequestComplete(
const ResponseValue& aResponseValue)
{
NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
if (aResponseValue.type() == ResponseValue::Tnsresult) {
NS_ASSERTION(NS_FAILED(aResponseValue.get_nsresult()), "Huh?");
SetError(aResponseValue.get_nsresult());
}
else {
nsresult rv = UnpackResponseFromParentProcess(aResponseValue);
NS_ENSURE_SUCCESS(rv, rv);
}
return Run();
}
// static
nsresult
AsyncConnectionHelper::ConvertToArrayAndCleanup(
JSContext* aCx,
nsTArray<StructuredCloneReadInfo>& aReadInfos,
JS::MutableHandle<JS::Value> aResult)
{
NS_ASSERTION(aCx, "Null context!");
NS_ASSERTION(aResult.address(), "Null pointer!");
nsresult rv = ConvertCloneReadInfosToArrayInternal(aCx, aReadInfos, aResult);
for (uint32_t index = 0; index < aReadInfos.Length(); index++) {
aReadInfos[index].mCloneBuffer.clear();
}
aReadInfos.Clear();
return rv;
}
NS_IMETHODIMP_(MozExternalRefCountType)
StackBasedEventTarget::AddRef()
{
NS_NOTREACHED("Don't call me!");
return 2;
}
NS_IMETHODIMP_(MozExternalRefCountType)
StackBasedEventTarget::Release()
{
NS_NOTREACHED("Don't call me!");
return 1;
}
NS_IMETHODIMP
StackBasedEventTarget::QueryInterface(REFNSIID aIID,
void** aInstancePtr)
{
NS_NOTREACHED("Don't call me!");
return NS_NOINTERFACE;
}
NS_IMETHODIMP
ImmediateRunEventTarget::Dispatch(nsIRunnable* aRunnable,
uint32_t aFlags)
{
NS_ASSERTION(aRunnable, "Null pointer!");
nsCOMPtr<nsIRunnable> runnable(aRunnable);
DebugOnly<nsresult> rv =
runnable->Run();
MOZ_ASSERT(NS_SUCCEEDED(rv));
return NS_OK;
}
NS_IMETHODIMP
ImmediateRunEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
{
*aIsOnCurrentThread = true;
return NS_OK;
}
NS_IMETHODIMP
TransactionPoolEventTarget::Dispatch(nsIRunnable* aRunnable,
uint32_t aFlags)
{
NS_ASSERTION(aRunnable, "Null pointer!");
NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "Unsupported!");
TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
NS_ENSURE_TRUE(pool, NS_ERROR_UNEXPECTED);
nsresult rv = pool->Dispatch(mTransaction, aRunnable, false, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
TransactionPoolEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
{
*aIsOnCurrentThread = false;
return NS_OK;
}
NS_IMETHODIMP
NoDispatchEventTarget::Dispatch(nsIRunnable* aRunnable,
uint32_t aFlags)
{
nsCOMPtr<nsIRunnable> runnable = aRunnable;
return NS_OK;
}
NS_IMETHODIMP
NoDispatchEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
{
*aIsOnCurrentThread = true;
return NS_OK;
}

View File

@ -1,257 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_indexeddb_asyncconnectionhelper_h__
#define mozilla_dom_indexeddb_asyncconnectionhelper_h__
// Only meant to be included in IndexedDB source files, not exported.
#include "DatabaseInfo.h"
#include "IndexedDatabase.h"
#include "IDBDatabase.h"
#include "IDBRequest.h"
#include "mozIStorageProgressHandler.h"
#include "nsIEventTarget.h"
#include "nsIRunnable.h"
class mozIStorageConnection;
BEGIN_INDEXEDDB_NAMESPACE
class AutoSetCurrentTransaction;
class IDBTransaction;
namespace ipc {
class ResponseValue;
}
// A common base class for AsyncConnectionHelper and OpenDatabaseHelper that
// IDBRequest can use.
class HelperBase : public nsIRunnable
{
friend class IDBRequest;
public:
virtual nsresult GetResultCode() = 0;
virtual nsresult GetSuccessResult(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal) = 0;
IDBRequest* GetRequest() const
{
return mRequest;
}
protected:
explicit HelperBase(IDBRequest* aRequest)
: mRequest(aRequest)
{ }
virtual ~HelperBase();
/**
* Helper to wrap a native into a jsval. Uses the global object of the request
* to parent the native.
*/
nsresult WrapNative(JSContext* aCx,
nsISupports* aNative,
JS::MutableHandle<JS::Value> aResult);
/**
* Gives the subclass a chance to release any objects that must be released
* on the main thread, regardless of success or failure. Subclasses that
* implement this method *MUST* call the base class implementation as well.
*/
virtual void ReleaseMainThreadObjects();
nsRefPtr<IDBRequest> mRequest;
};
/**
* Must be subclassed. The subclass must implement DoDatabaseWork. It may then
* choose to implement OnSuccess and OnError depending on the needs of the
* subclass. If the default implementation of OnSuccess is desired then the
* subclass can implement GetSuccessResult to properly set the result of the
* success event. Call Dispatch to start the database operation. Must be created
* and Dispatched from the main thread only. Target thread may not be the main
* thread.
*/
class AsyncConnectionHelper : public HelperBase,
public mozIStorageProgressHandler
{
friend class AutoSetCurrentTransaction;
public:
typedef ipc::ResponseValue ResponseValue;
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_MOZISTORAGEPROGRESSHANDLER
virtual nsresult Dispatch(nsIEventTarget* aDatabaseThread);
// Only for transactions!
nsresult DispatchToTransactionPool();
void SetError(nsresult aErrorCode)
{
NS_ASSERTION(NS_FAILED(aErrorCode), "Not a failure code!");
mResultCode = aErrorCode;
}
static IDBTransaction* GetCurrentTransaction();
bool HasTransaction() const
{
return !!mTransaction;
}
IDBTransaction* GetTransaction() const
{
return mTransaction;
}
virtual nsresult GetResultCode() MOZ_OVERRIDE
{
return mResultCode;
}
enum ChildProcessSendResult
{
// The result was successfully sent to the child process
Success_Sent = 0,
// The result was not sent, because this is not an out-of-process request.
Success_NotSent,
// The result was not sent, because the actor has been disconnected
// (if the child process has shut down or crashed).
Success_ActorDisconnected,
// An error occurred.
Error
};
ChildProcessSendResult
MaybeSendResponseToChildProcess(nsresult aResultCode);
virtual nsresult OnParentProcessRequestComplete(
const ResponseValue& aResponseValue);
virtual nsresult
UnpackResponseFromParentProcess(const ResponseValue& aResponseValue) = 0;
protected:
AsyncConnectionHelper(IDBDatabase* aDatabase,
IDBRequest* aRequest);
AsyncConnectionHelper(IDBTransaction* aTransaction,
IDBRequest* aRequest);
virtual ~AsyncConnectionHelper();
/**
* This is called on the main thread after Dispatch is called but before the
* runnable is actually dispatched to the database thread. Allows the subclass
* to initialize itself.
*/
virtual nsresult Init();
/**
* This callback is run on the database thread.
*/
virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection) = 0;
/**
* This function returns the event to be dispatched at the request when
* OnSuccess is called. A subclass can override this to fire an event other
* than "success" at the request.
*/
virtual already_AddRefed<nsIDOMEvent> CreateSuccessEvent(
mozilla::dom::EventTarget* aOwner);
/**
* This callback is run on the main thread if DoDatabaseWork returned NS_OK.
* The default implementation fires a "success" DOM event with its target set
* to the request. Returning anything other than NS_OK from the OnSuccess
* callback will trigger the OnError callback.
*/
virtual nsresult OnSuccess();
/**
* This callback is run on the main thread if DoDatabaseWork or OnSuccess
* returned an error code. The default implementation fires an "error" DOM
* event with its target set to the request.
*/
virtual void OnError();
/**
* This function is called by the request on the main thread when script
* accesses the result property of the request.
*/
virtual nsresult GetSuccessResult(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
/**
* Gives the subclass a chance to release any objects that must be released
* on the main thread, regardless of success or failure. Subclasses that
* implement this method *MUST* call the base class implementation as well.
*/
virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
/**
* Helper to make a JS array object out of an array of clone buffers.
*/
static nsresult ConvertToArrayAndCleanup(
JSContext* aCx,
nsTArray<StructuredCloneReadInfo>& aReadInfos,
JS::MutableHandle<JS::Value> aResult);
/**
* This should only be called by AutoSetCurrentTransaction.
*/
static void SetCurrentTransaction(IDBTransaction* aTransaction);
/**
* Allows the subclass to send its results to the child process. Will only
* be called if all of the IPC infrastructure is available (there is an
* actor, the child is stil alive and hasn't begun shutting down).
*/
virtual ChildProcessSendResult
SendResponseToChildProcess(nsresult aResultCode) = 0;
protected:
nsRefPtr<IDBDatabase> mDatabase;
nsRefPtr<IDBTransaction> mTransaction;
private:
nsCOMPtr<mozIStorageProgressHandler> mOldProgressHandler;
nsresult mResultCode;
bool mDispatched;
};
class MOZ_STACK_CLASS StackBasedEventTarget : public nsIEventTarget
{
public:
NS_DECL_ISUPPORTS_INHERITED
};
class MOZ_STACK_CLASS ImmediateRunEventTarget : public StackBasedEventTarget
{
public:
NS_DECL_NSIEVENTTARGET
};
class MOZ_STACK_CLASS NoDispatchEventTarget : public StackBasedEventTarget
{
public:
NS_DECL_NSIEVENTTARGET
};
END_INDEXEDDB_NAMESPACE
#endif // mozilla_dom_indexeddb_asyncconnectionhelper_h__

View File

@ -1,220 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CheckPermissionsHelper.h"
#include "nsIDOMWindow.h"
#include "nsILoadContext.h"
#include "nsIWebNavigation.h"
#include "nsIObserverService.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIURI.h"
#include "CheckQuotaHelper.h"
#include "nsContentUtils.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
#include "mozilla/Services.h"
#include "IndexedDatabaseManager.h"
#define PERMISSION_INDEXEDDB "indexedDB"
#define TOPIC_PERMISSIONS_PROMPT "indexedDB-permissions-prompt"
#define TOPIC_PERMISSIONS_RESPONSE "indexedDB-permissions-response"
// This is a little confusing, but our default behavior (UNKNOWN_ACTION) is to
// allow access without a prompt. If the "indexedDB" permission is set to
// ALLOW_ACTION then we will issue a prompt before allowing access. Otherwise
// (DENY_ACTION) we deny access.
#define PERMISSION_ALLOWED nsIPermissionManager::UNKNOWN_ACTION
#define PERMISSION_DENIED nsIPermissionManager::DENY_ACTION
#define PERMISSION_PROMPT nsIPermissionManager::ALLOW_ACTION
USING_INDEXEDDB_NAMESPACE
using namespace mozilla::services;
using mozilla::dom::quota::CheckQuotaHelper;
namespace {
inline
uint32_t
GetIndexedDBPermissions(nsIDOMWindow* aWindow)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aWindow, "Chrome shouldn't check the permission!");
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(aWindow));
NS_ENSURE_TRUE(sop, nsIPermissionManager::DENY_ACTION);
NS_ASSERTION(!nsContentUtils::IsSystemPrincipal(sop->GetPrincipal()),
"Chrome windows shouldn't check the permission!");
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
if (loadContext && loadContext->UsePrivateBrowsing()) {
// TODO Support private browsing indexedDB?
NS_WARNING("IndexedDB may not be used while in private browsing mode!");
return PERMISSION_DENIED;
}
nsCOMPtr<nsIPermissionManager> permissionManager = GetPermissionManager();
NS_ENSURE_TRUE(permissionManager, PERMISSION_DENIED);
uint32_t permission;
nsresult rv =
permissionManager->TestPermissionFromPrincipal(sop->GetPrincipal(),
PERMISSION_INDEXEDDB,
&permission);
NS_ENSURE_SUCCESS(rv, PERMISSION_DENIED);
return permission;
}
} // anonymous namespace
NS_IMPL_ISUPPORTS(CheckPermissionsHelper, nsIRunnable,
nsIInterfaceRequestor,
nsIObserver)
NS_IMETHODIMP
CheckPermissionsHelper::Run()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
uint32_t permission = mHasPrompted ?
mPromptResult :
GetIndexedDBPermissions(mWindow);
nsresult rv;
if (mHasPrompted) {
// Add permissions to the database, but only if we are in the parent
// process (if we are in the child process, we have already
// set the permission when the prompt was shown in the parent, as
// we cannot set the permission from the child).
if (permission != PERMISSION_PROMPT &&
IndexedDatabaseManager::IsMainProcess()) {
NS_ASSERTION(mWindow, "Null window!");
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(mWindow);
NS_ASSERTION(sop, "Window didn't QI to nsIScriptObjectPrincipal!");
nsIPrincipal* windowPrincipal = sop->GetPrincipal();
NS_ASSERTION(windowPrincipal, "Null principal!");
nsCOMPtr<nsIPermissionManager> permissionManager = GetPermissionManager();
NS_ENSURE_STATE(permissionManager);
rv = permissionManager->AddFromPrincipal(windowPrincipal,
PERMISSION_INDEXEDDB, permission,
nsIPermissionManager::EXPIRE_NEVER,
0);
NS_ENSURE_SUCCESS(rv, rv);
}
}
else if (permission == PERMISSION_PROMPT && mPromptAllowed) {
nsCOMPtr<nsIObserverService> obs = GetObserverService();
rv = obs->NotifyObservers(static_cast<nsIRunnable*>(this),
TOPIC_PERMISSIONS_PROMPT, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsRefPtr<OpenDatabaseHelper> helper;
helper.swap(mHelper);
nsCOMPtr<nsIDOMWindow> window;
window.swap(mWindow);
if (permission == PERMISSION_ALLOWED) {
// If we're running from a window then we should check the quota permission
// as well. If we don't have a window then we're opening a chrome database
// and the quota will be unlimited already.
if (window) {
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(window);
NS_ASSERTION(sop, "Window didn't QI to nsIScriptObjectPrincipal!");
nsIPrincipal* windowPrincipal = sop->GetPrincipal();
NS_ASSERTION(windowPrincipal, "Null principal!");
uint32_t quotaPermission =
CheckQuotaHelper::GetQuotaPermission(windowPrincipal);
if (quotaPermission == nsIPermissionManager::ALLOW_ACTION) {
helper->SetUnlimitedQuotaAllowed();
}
}
return helper->DispatchToIOThread();
}
NS_ASSERTION(permission == PERMISSION_PROMPT ||
permission == PERMISSION_DENIED,
"Unknown permission!");
helper->SetError(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return helper->RunImmediately();
}
NS_IMETHODIMP
CheckPermissionsHelper::GetInterface(const nsIID& aIID,
void** aResult)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (aIID.Equals(NS_GET_IID(nsIObserver))) {
return QueryInterface(aIID, aResult);
}
if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
return mWindow->QueryInterface(aIID, aResult);
}
*aResult = nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
CheckPermissionsHelper::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!strcmp(aTopic, TOPIC_PERMISSIONS_RESPONSE), "Bad topic!");
NS_ASSERTION(mPromptAllowed, "How did we get here?");
mHasPrompted = true;
nsresult rv;
uint32_t promptResult = nsDependentString(aData).ToInteger(&rv);
NS_ENSURE_SUCCESS(rv, rv);
// Have to convert the permission we got from the user to our weird reversed
// permission type.
switch (promptResult) {
case nsIPermissionManager::ALLOW_ACTION:
mPromptResult = PERMISSION_ALLOWED;
break;
case nsIPermissionManager::DENY_ACTION:
mPromptResult = PERMISSION_DENIED;
break;
case nsIPermissionManager::UNKNOWN_ACTION:
mPromptResult = PERMISSION_PROMPT;
break;
default:
NS_NOTREACHED("Unknown permission type!");
mPromptResult = PERMISSION_DENIED;
}
rv = NS_DispatchToCurrentThread(this);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}

View File

@ -1,59 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_indexeddb_checkpermissionshelper_h__
#define mozilla_dom_indexeddb_checkpermissionshelper_h__
// Only meant to be included in IndexedDB source files, not exported.
#include "OpenDatabaseHelper.h"
#include "nsIInterfaceRequestor.h"
#include "nsIObserver.h"
#include "nsIRunnable.h"
class nsIDOMWindow;
class nsIThread;
BEGIN_INDEXEDDB_NAMESPACE
class CheckPermissionsHelper MOZ_FINAL : public nsIRunnable,
public nsIInterfaceRequestor,
public nsIObserver
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIOBSERVER
CheckPermissionsHelper(OpenDatabaseHelper* aHelper,
nsIDOMWindow* aWindow)
: mHelper(aHelper),
mWindow(aWindow),
// If we're trying to delete the database, we should never prompt the user.
// Anything that would prompt is translated to denied.
mPromptAllowed(!aHelper->mForDeletion),
mHasPrompted(false),
mPromptResult(0)
{
NS_ASSERTION(aHelper, "Null pointer!");
NS_ASSERTION(aHelper->mPersistenceType == quota::PERSISTENCE_TYPE_PERSISTENT,
"Checking permission for non persistent databases?!");
}
private:
~CheckPermissionsHelper() {}
nsRefPtr<OpenDatabaseHelper> mHelper;
nsCOMPtr<nsIDOMWindow> mWindow;
bool mPromptAllowed;
bool mHasPrompted;
uint32_t mPromptResult;
};
END_INDEXEDDB_NAMESPACE
#endif // mozilla_dom_indexeddb_checkpermissionshelper_h__

View File

@ -1,369 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Client.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/UsageInfo.h"
#include "mozilla/dom/quota/Utilities.h"
#include "IDBDatabase.h"
#include "IndexedDatabaseManager.h"
#include "TransactionThreadPool.h"
#include "nsISimpleEnumerator.h"
USING_INDEXEDDB_NAMESPACE
using mozilla::dom::quota::AssertIsOnIOThread;
using mozilla::dom::quota::QuotaManager;
namespace {
bool
GetDatabaseBaseFilename(const nsAString& aFilename,
nsAString& aDatabaseBaseFilename)
{
NS_ASSERTION(!aFilename.IsEmpty(), "Bad argument!");
NS_NAMED_LITERAL_STRING(sqlite, ".sqlite");
if (!StringEndsWith(aFilename, sqlite)) {
return false;
}
aDatabaseBaseFilename =
Substring(aFilename, 0, aFilename.Length() - sqlite.Length());
return true;
}
} // anonymous namespace
// This needs to be fully qualified to not confuse trace refcnt assertions.
NS_IMPL_ADDREF(mozilla::dom::indexedDB::Client)
NS_IMPL_RELEASE(mozilla::dom::indexedDB::Client)
nsresult
Client::InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin, UsageInfo* aUsageInfo)
{
AssertIsOnIOThread();
nsCOMPtr<nsIFile> directory;
nsresult rv =
GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
// We need to see if there are any files in the directory already. If they
// are database files then we need to cleanup stored files (if it's needed)
// and also get the usage.
nsAutoTArray<nsString, 20> subdirsToProcess;
nsAutoTArray<nsCOMPtr<nsIFile>, 20> unknownFiles;
nsTHashtable<nsStringHashKey> validSubdirs(20);
nsCOMPtr<nsISimpleEnumerator> entries;
rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
NS_ENSURE_SUCCESS(rv, rv);
bool hasMore;
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
hasMore && (!aUsageInfo || !aUsageInfo->Canceled())) {
nsCOMPtr<nsISupports> entry;
rv = entries->GetNext(getter_AddRefs(entry));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
NS_ENSURE_TRUE(file, NS_NOINTERFACE);
nsString leafName;
rv = file->GetLeafName(leafName);
NS_ENSURE_SUCCESS(rv, rv);
if (StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
continue;
}
if (leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
continue;
}
bool isDirectory;
rv = file->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, rv);
if (isDirectory) {
if (!validSubdirs.GetEntry(leafName)) {
subdirsToProcess.AppendElement(leafName);
}
continue;
}
nsString dbBaseFilename;
if (!GetDatabaseBaseFilename(leafName, dbBaseFilename)) {
unknownFiles.AppendElement(file);
continue;
}
nsCOMPtr<nsIFile> fmDirectory;
rv = directory->Clone(getter_AddRefs(fmDirectory));
NS_ENSURE_SUCCESS(rv, rv);
rv = fmDirectory->Append(dbBaseFilename);
NS_ENSURE_SUCCESS(rv, rv);
rv = FileManager::InitDirectory(fmDirectory, file, aPersistenceType, aGroup,
aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
if (aUsageInfo) {
int64_t fileSize;
rv = file->GetFileSize(&fileSize);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(fileSize >= 0, "Negative size?!");
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
uint64_t usage;
rv = FileManager::GetUsage(fmDirectory, &usage);
NS_ENSURE_SUCCESS(rv, rv);
aUsageInfo->AppendToFileUsage(usage);
}
validSubdirs.PutEntry(dbBaseFilename);
}
NS_ENSURE_SUCCESS(rv, rv);
for (uint32_t i = 0; i < subdirsToProcess.Length(); i++) {
const nsString& subdir = subdirsToProcess[i];
if (!validSubdirs.GetEntry(subdir)) {
NS_WARNING("Unknown subdirectory found!");
return NS_ERROR_UNEXPECTED;
}
}
for (uint32_t i = 0; i < unknownFiles.Length(); i++) {
nsCOMPtr<nsIFile>& unknownFile = unknownFiles[i];
// Some temporary SQLite files could disappear, so we have to check if the
// unknown file still exists.
bool exists;
rv = unknownFile->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (exists) {
nsString leafName;
unknownFile->GetLeafName(leafName);
// The journal file may exists even after db has been correctly opened.
if (!StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
NS_WARNING("Unknown file found!");
return NS_ERROR_UNEXPECTED;
}
}
}
return NS_OK;
}
nsresult
Client::GetUsageForOrigin(PersistenceType aPersistenceType,
const nsACString& aGroup, const nsACString& aOrigin,
UsageInfo* aUsageInfo)
{
AssertIsOnIOThread();
NS_ASSERTION(aUsageInfo, "Null pointer!");
nsCOMPtr<nsIFile> directory;
nsresult rv =
GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetUsageForDirectoryInternal(directory, aUsageInfo, true);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
void
Client::OnOriginClearCompleted(PersistenceType aPersistenceType,
const OriginOrPatternString& aOriginOrPattern)
{
AssertIsOnIOThread();
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
if (mgr) {
mgr->InvalidateFileManagers(aPersistenceType, aOriginOrPattern);
}
}
void
Client::ReleaseIOThreadObjects()
{
AssertIsOnIOThread();
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
if (mgr) {
mgr->InvalidateAllFileManagers();
}
}
bool
Client::IsTransactionServiceActivated()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return !!TransactionThreadPool::Get();
}
void
Client::WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
nsIRunnable* aCallback)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!aStorages.IsEmpty(), "No storages to wait on!");
NS_ASSERTION(aCallback, "Passed null callback!");
TransactionThreadPool* pool = TransactionThreadPool::Get();
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
nsTArray<nsRefPtr<IDBDatabase> > databases(aStorages.Length());
for (uint32_t index = 0; index < aStorages.Length(); index++) {
IDBDatabase* database = IDBDatabase::FromStorage(aStorages[index]);
if (!database) {
MOZ_CRASH();
}
databases.AppendElement(database);
}
pool->WaitForDatabasesToComplete(databases, aCallback);
}
void
Client::AbortTransactionsForStorage(nsIOfflineStorage* aStorage)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aStorage, "Passed null storage!");
TransactionThreadPool* pool = TransactionThreadPool::Get();
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
NS_ASSERTION(database, "This shouldn't be null!");
pool->AbortTransactionsForDatabase(database);
}
bool
Client::HasTransactionsForStorage(nsIOfflineStorage* aStorage)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
TransactionThreadPool* pool = TransactionThreadPool::Get();
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
NS_ASSERTION(database, "This shouldn't be null!");
return pool->HasTransactionsForDatabase(database);
}
void
Client::ShutdownTransactionService()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
TransactionThreadPool::Shutdown();
}
nsresult
Client::GetDirectory(PersistenceType aPersistenceType,
const nsACString& aOrigin, nsIFile** aDirectory)
{
QuotaManager* quotaManager = QuotaManager::Get();
NS_ASSERTION(quotaManager, "This should never fail!");
nsCOMPtr<nsIFile> directory;
nsresult rv = quotaManager->GetDirectoryForOrigin(aPersistenceType, aOrigin,
getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(directory, "What?");
rv = directory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME));
NS_ENSURE_SUCCESS(rv, rv);
directory.forget(aDirectory);
return NS_OK;
}
nsresult
Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
UsageInfo* aUsageInfo,
bool aDatabaseFiles)
{
NS_ASSERTION(aDirectory, "Null pointer!");
NS_ASSERTION(aUsageInfo, "Null pointer!");
nsCOMPtr<nsISimpleEnumerator> entries;
nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
NS_ENSURE_SUCCESS(rv, rv);
if (!entries) {
return NS_OK;
}
bool hasMore;
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
hasMore && !aUsageInfo->Canceled()) {
nsCOMPtr<nsISupports> entry;
rv = entries->GetNext(getter_AddRefs(entry));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> file(do_QueryInterface(entry));
NS_ASSERTION(file, "Don't know what this is!");
bool isDirectory;
rv = file->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, rv);
if (isDirectory) {
if (aDatabaseFiles) {
rv = GetUsageForDirectoryInternal(file, aUsageInfo, false);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsString leafName;
rv = file->GetLeafName(leafName);
NS_ENSURE_SUCCESS(rv, rv);
if (!leafName.EqualsLiteral(JOURNAL_DIRECTORY_NAME)) {
NS_WARNING("Unknown directory found!");
}
}
continue;
}
int64_t fileSize;
rv = file->GetFileSize(&fileSize);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(fileSize >= 0, "Negative size?!");
if (aDatabaseFiles) {
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
}
else {
aUsageInfo->AppendToFileUsage(uint64_t(fileSize));
}
}
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}

View File

@ -1,97 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_indexeddb_client_h__
#define mozilla_dom_indexeddb_client_h__
#include "IndexedDatabase.h"
#include "mozilla/dom/quota/Client.h"
#define JOURNAL_DIRECTORY_NAME "journals"
BEGIN_INDEXEDDB_NAMESPACE
class Client : public mozilla::dom::quota::Client
{
typedef mozilla::dom::quota::OriginOrPatternString OriginOrPatternString;
typedef mozilla::dom::quota::PersistenceType PersistenceType;
typedef mozilla::dom::quota::UsageInfo UsageInfo;
public:
NS_IMETHOD_(MozExternalRefCountType)
AddRef() MOZ_OVERRIDE;
NS_IMETHOD_(MozExternalRefCountType)
Release() MOZ_OVERRIDE;
virtual Type
GetType() MOZ_OVERRIDE
{
return IDB;
}
virtual nsresult
InitOrigin(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
UsageInfo* aUsageInfo) MOZ_OVERRIDE;
virtual nsresult
GetUsageForOrigin(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
UsageInfo* aUsageInfo) MOZ_OVERRIDE;
virtual void
OnOriginClearCompleted(PersistenceType aPersistenceType,
const OriginOrPatternString& aOriginOrPattern)
MOZ_OVERRIDE;
virtual void
ReleaseIOThreadObjects() MOZ_OVERRIDE;
virtual bool
IsFileServiceUtilized() MOZ_OVERRIDE
{
return true;
}
virtual bool
IsTransactionServiceActivated() MOZ_OVERRIDE;
virtual void
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
nsIRunnable* aCallback) MOZ_OVERRIDE;
virtual void
AbortTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE;
virtual bool
HasTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE;
virtual void
ShutdownTransactionService() MOZ_OVERRIDE;
private:
~Client() {}
nsresult
GetDirectory(PersistenceType aPersistenceType, const nsACString& aOrigin,
nsIFile** aDirectory);
nsresult
GetUsageForDirectoryInternal(nsIFile* aDirectory,
UsageInfo* aUsageInfo,
bool aDatabaseFiles);
nsAutoRefCnt mRefCnt;
NS_DECL_OWNINGTHREAD
};
END_INDEXEDDB_NAMESPACE
#endif // mozilla_dom_indexeddb_client_h__

View File

@ -1,269 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DatabaseInfo.h"
#include "nsDataHashtable.h"
#include "nsThreadUtils.h"
USING_INDEXEDDB_NAMESPACE
namespace {
typedef nsDataHashtable<nsCStringHashKey, DatabaseInfo*>
DatabaseHash;
DatabaseHash* gDatabaseHash = nullptr;
PLDHashOperator
EnumerateObjectStoreNames(const nsAString& aKey,
ObjectStoreInfo* aData,
void* aUserArg)
{
nsTArray<nsString>* array = static_cast<nsTArray<nsString>*>(aUserArg);
if (!array->InsertElementSorted(aData->name)) {
NS_ERROR("Out of memory?");
return PL_DHASH_STOP;
}
return PL_DHASH_NEXT;
}
PLDHashOperator
CloneObjectStoreInfo(const nsAString& aKey,
ObjectStoreInfo* aData,
void* aUserArg)
{
ObjectStoreInfoHash* hash = static_cast<ObjectStoreInfoHash*>(aUserArg);
nsRefPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo(*aData));
hash->Put(aKey, newInfo);
return PL_DHASH_NEXT;
}
}
DatabaseInfo::~DatabaseInfo()
{
// Clones are never in the hash.
if (!cloned) {
DatabaseInfo::Remove(id);
}
}
ObjectStoreInfo::ObjectStoreInfo(ObjectStoreInfo& aOther)
: nextAutoIncrementId(aOther.nextAutoIncrementId),
comittedAutoIncrementId(aOther.comittedAutoIncrementId)
{
*static_cast<ObjectStoreInfoGuts*>(this) =
static_cast<ObjectStoreInfoGuts&>(aOther);
// Doesn't copy the refcount
MOZ_COUNT_CTOR(ObjectStoreInfo);
}
#ifdef NS_BUILD_REFCNT_LOGGING
IndexInfo::IndexInfo()
: id(INT64_MIN),
keyPath(0),
unique(false),
multiEntry(false)
{
MOZ_COUNT_CTOR(IndexInfo);
}
IndexInfo::IndexInfo(const IndexInfo& aOther)
: name(aOther.name),
id(aOther.id),
keyPath(aOther.keyPath),
unique(aOther.unique),
multiEntry(aOther.multiEntry)
{
MOZ_COUNT_CTOR(IndexInfo);
}
IndexInfo::~IndexInfo()
{
MOZ_COUNT_DTOR(IndexInfo);
}
ObjectStoreInfo::ObjectStoreInfo()
: nextAutoIncrementId(0),
comittedAutoIncrementId(0)
{
MOZ_COUNT_CTOR(ObjectStoreInfo);
}
ObjectStoreInfo::~ObjectStoreInfo()
{
MOZ_COUNT_DTOR(ObjectStoreInfo);
}
IndexUpdateInfo::IndexUpdateInfo()
: indexId(0),
indexUnique(false)
{
MOZ_COUNT_CTOR(IndexUpdateInfo);
}
IndexUpdateInfo::IndexUpdateInfo(const IndexUpdateInfo& aOther)
: indexId(aOther.indexId),
indexUnique(aOther.indexUnique),
value(aOther.value)
{
MOZ_COUNT_CTOR(IndexUpdateInfo);
}
IndexUpdateInfo::~IndexUpdateInfo()
{
MOZ_COUNT_DTOR(IndexUpdateInfo);
}
#endif /* NS_BUILD_REFCNT_LOGGING */
// static
bool
DatabaseInfo::Get(const nsACString& aId,
DatabaseInfo** aInfo)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!aId.IsEmpty(), "Bad id!");
if (gDatabaseHash &&
gDatabaseHash->Get(aId, aInfo)) {
NS_IF_ADDREF(*aInfo);
return true;
}
return false;
}
// static
bool
DatabaseInfo::Put(DatabaseInfo* aInfo)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aInfo, "Null pointer!");
if (!gDatabaseHash) {
nsAutoPtr<DatabaseHash> databaseHash(new DatabaseHash());
gDatabaseHash = databaseHash.forget();
}
if (gDatabaseHash->Get(aInfo->id, nullptr)) {
NS_ERROR("Already know about this database!");
return false;
}
gDatabaseHash->Put(aInfo->id, aInfo);
return true;
}
// static
void
DatabaseInfo::Remove(const nsACString& aId)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (gDatabaseHash) {
gDatabaseHash->Remove(aId);
if (!gDatabaseHash->Count()) {
delete gDatabaseHash;
gDatabaseHash = nullptr;
}
}
}
bool
DatabaseInfo::GetObjectStoreNames(nsTArray<nsString>& aNames)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
aNames.Clear();
if (objectStoreHash) {
objectStoreHash->EnumerateRead(EnumerateObjectStoreNames, &aNames);
}
return true;
}
bool
DatabaseInfo::ContainsStoreName(const nsAString& aName)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return objectStoreHash && objectStoreHash->Get(aName, nullptr);
}
ObjectStoreInfo*
DatabaseInfo::GetObjectStore(const nsAString& aName)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (objectStoreHash) {
return objectStoreHash->GetWeak(aName);
}
return nullptr;
}
bool
DatabaseInfo::PutObjectStore(ObjectStoreInfo* aInfo)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aInfo, "Null pointer!");
if (!objectStoreHash) {
nsAutoPtr<ObjectStoreInfoHash> hash(new ObjectStoreInfoHash());
objectStoreHash = hash.forget();
}
if (objectStoreHash->Get(aInfo->name, nullptr)) {
NS_ERROR("Already have an entry for this objectstore!");
return false;
}
objectStoreHash->Put(aInfo->name, aInfo);
return true;
}
void
DatabaseInfo::RemoveObjectStore(const nsAString& aName)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(GetObjectStore(aName), "Don't know about this one!");
if (objectStoreHash) {
objectStoreHash->Remove(aName);
}
}
already_AddRefed<DatabaseInfo>
DatabaseInfo::Clone()
{
nsRefPtr<DatabaseInfo> dbInfo(new DatabaseInfo());
dbInfo->cloned = true;
dbInfo->name = name;
dbInfo->group = group;
dbInfo->origin = origin;
dbInfo->version = version;
dbInfo->persistenceType = persistenceType;
dbInfo->id = id;
dbInfo->filePath = filePath;
dbInfo->nextObjectStoreId = nextObjectStoreId;
dbInfo->nextIndexId = nextIndexId;
if (objectStoreHash) {
dbInfo->objectStoreHash = new ObjectStoreInfoHash();
objectStoreHash->EnumerateRead(CloneObjectStoreInfo,
dbInfo->objectStoreHash);
}
return dbInfo.forget();
}

View File

@ -1,203 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_indexeddb_databaseinfo_h__
#define mozilla_dom_indexeddb_databaseinfo_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "nsRefPtrHashtable.h"
#include "nsHashKeys.h"
#include "mozilla/dom/indexedDB/Key.h"
#include "mozilla/dom/indexedDB/KeyPath.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
BEGIN_INDEXEDDB_NAMESPACE
class IndexedDBDatabaseChild;
struct ObjectStoreInfo;
typedef nsRefPtrHashtable<nsStringHashKey, ObjectStoreInfo>
ObjectStoreInfoHash;
struct DatabaseInfoGuts
{
typedef mozilla::dom::quota::PersistenceType PersistenceType;
DatabaseInfoGuts()
: nextObjectStoreId(1), nextIndexId(1)
{ }
bool operator==(const DatabaseInfoGuts& aOther) const
{
return this->name == aOther.name &&
this->group == aOther.group &&
this->origin == aOther.origin &&
this->version == aOther.version &&
this->persistenceType == aOther.persistenceType &&
this->nextObjectStoreId == aOther.nextObjectStoreId &&
this->nextIndexId == aOther.nextIndexId;
};
// Make sure to update ipc/SerializationHelpers.h when changing members here!
nsString name;
nsCString group;
nsCString origin;
uint64_t version;
PersistenceType persistenceType;
int64_t nextObjectStoreId;
int64_t nextIndexId;
};
struct DatabaseInfo MOZ_FINAL : public DatabaseInfoGuts
{
DatabaseInfo()
: cloned(false)
{ }
private:
// Private destructor, to discourage deletion outside of Release():
~DatabaseInfo();
public:
static bool Get(const nsACString& aId,
DatabaseInfo** aInfo);
static bool Put(DatabaseInfo* aInfo);
static void Remove(const nsACString& aId);
bool GetObjectStoreNames(nsTArray<nsString>& aNames);
bool ContainsStoreName(const nsAString& aName);
ObjectStoreInfo* GetObjectStore(const nsAString& aName);
bool PutObjectStore(ObjectStoreInfo* aInfo);
void RemoveObjectStore(const nsAString& aName);
already_AddRefed<DatabaseInfo> Clone();
nsCString id;
nsString filePath;
bool cloned;
nsAutoPtr<ObjectStoreInfoHash> objectStoreHash;
NS_INLINE_DECL_REFCOUNTING(DatabaseInfo)
};
struct IndexInfo
{
#ifdef NS_BUILD_REFCNT_LOGGING
IndexInfo();
IndexInfo(const IndexInfo& aOther);
~IndexInfo();
#else
IndexInfo()
: id(INT64_MIN), keyPath(0), unique(false), multiEntry(false) { }
#endif
bool operator==(const IndexInfo& aOther) const
{
return this->name == aOther.name &&
this->id == aOther.id &&
this->keyPath == aOther.keyPath &&
this->unique == aOther.unique &&
this->multiEntry == aOther.multiEntry;
};
// Make sure to update ipc/SerializationHelpers.h when changing members here!
nsString name;
int64_t id;
KeyPath keyPath;
bool unique;
bool multiEntry;
};
struct ObjectStoreInfoGuts
{
ObjectStoreInfoGuts()
: id(0), keyPath(0), autoIncrement(false)
{ }
bool operator==(const ObjectStoreInfoGuts& aOther) const
{
return this->name == aOther.name &&
this->id == aOther.id;
};
// Make sure to update ipc/SerializationHelpers.h when changing members here!
// Constant members, can be gotten on any thread
nsString name;
int64_t id;
KeyPath keyPath;
bool autoIncrement;
// Main-thread only members. This must *not* be touched on the database
// thread.
nsTArray<IndexInfo> indexes;
};
struct ObjectStoreInfo MOZ_FINAL : public ObjectStoreInfoGuts
{
#ifdef NS_BUILD_REFCNT_LOGGING
ObjectStoreInfo();
#else
ObjectStoreInfo()
: nextAutoIncrementId(0), comittedAutoIncrementId(0) { }
#endif
ObjectStoreInfo(ObjectStoreInfo& aOther);
private:
// Private destructor, to discourage deletion outside of Release():
#ifdef NS_BUILD_REFCNT_LOGGING
~ObjectStoreInfo();
#else
~ObjectStoreInfo() {}
#endif
public:
// Database-thread members. After the ObjectStoreInfo has been initialized,
// these can *only* be touced on the database thread.
int64_t nextAutoIncrementId;
int64_t comittedAutoIncrementId;
// This is threadsafe since the ObjectStoreInfos are created on the database
// thread but then only used from the main thread. Ideal would be if we
// could transfer ownership from the database thread to the main thread, but
// we don't have that ability yet.
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ObjectStoreInfo)
};
struct IndexUpdateInfo
{
#ifdef NS_BUILD_REFCNT_LOGGING
IndexUpdateInfo();
IndexUpdateInfo(const IndexUpdateInfo& aOther);
~IndexUpdateInfo();
#endif
bool operator==(const IndexUpdateInfo& aOther) const
{
return this->indexId == aOther.indexId &&
this->indexUnique == aOther.indexUnique &&
this->value == aOther.value;
};
// Make sure to update ipc/SerializationHelpers.h when changing members here!
int64_t indexId;
bool indexUnique;
Key value;
};
END_INDEXEDDB_NAMESPACE
#endif // mozilla_dom_indexeddb_databaseinfo_h__

View File

@ -5,68 +5,113 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FileInfo.h"
#include "nsThreadUtils.h"
#include "mozilla/dom/quota/QuotaManager.h"
USING_INDEXEDDB_NAMESPACE
#include "FileManager.h"
#include "IndexedDatabaseManager.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Mutex.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "nsError.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
namespace indexedDB {
using namespace mozilla::dom::quota;
namespace {
class CleanupFileRunnable MOZ_FINAL : public nsIRunnable
template <typename IdType>
class FileInfoImpl MOZ_FINAL
: public FileInfo
{
~CleanupFileRunnable() {}
IdType mFileId;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId);
FileInfoImpl(FileManager* aFileManager, IdType aFileId)
: FileInfo(aFileManager)
, mFileId(aFileId)
{
MOZ_ASSERT(aFileManager);
MOZ_ASSERT(aFileId > 0);
}
private:
~FileInfoImpl()
{ }
virtual int64_t
Id() const MOZ_OVERRIDE
{
return int64_t(mFileId);
}
};
class CleanupFileRunnable MOZ_FINAL
: public nsRunnable
{
nsRefPtr<FileManager> mFileManager;
int64_t mFileId;
public:
static void
DoCleanup(FileManager* aFileManager, int64_t aFileId);
CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId)
: mFileManager(aFileManager)
, mFileId(aFileId)
{
MOZ_ASSERT(aFileManager);
MOZ_ASSERT(aFileId > 0);
}
NS_DECL_ISUPPORTS_INHERITED
private:
~CleanupFileRunnable()
{ }
NS_DECL_NSIRUNNABLE
};
} // anonymous namespace
FileInfo::FileInfo(FileManager* aFileManager)
: mFileManager(aFileManager)
{
MOZ_ASSERT(aFileManager);
}
FileInfo::~FileInfo()
{
}
// static
FileInfo*
FileInfo::Create(FileManager* aFileManager, int64_t aId)
{
MOZ_ASSERT(aId > 0, "Wrong id!");
MOZ_ASSERT(aFileManager);
MOZ_ASSERT(aId > 0);
if (aId <= INT16_MAX) {
return new FileInfo16(aFileManager, aId);
return new FileInfoImpl<int16_t>(aFileManager, aId);
}
if (aId <= INT32_MAX) {
return new FileInfo32(aFileManager, aId);
return new FileInfoImpl<int32_t>(aFileManager, aId);
}
return new FileInfo64(aFileManager, aId);
return new FileInfoImpl<int64_t>(aFileManager, aId);
}
void
FileInfo::GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt,
FileInfo::GetReferences(int32_t* aRefCnt,
int32_t* aDBRefCnt,
int32_t* aSliceRefCnt)
{
if (IndexedDatabaseManager::IsClosed()) {
NS_ERROR("Shouldn't be called after shutdown!");
if (aRefCnt) {
*aRefCnt = -1;
}
if (aDBRefCnt) {
*aDBRefCnt = -1;
}
if (aSliceRefCnt) {
*aSliceRefCnt = -1;
}
return;
}
MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
@ -84,14 +129,31 @@ FileInfo::GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt,
}
void
FileInfo::UpdateReferences(mozilla::ThreadSafeAutoRefCnt& aRefCount,
int32_t aDelta, bool aClear)
FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount,
int32_t aDelta,
bool aClear)
{
// XXX This can go away once DOM objects no longer hold FileInfo objects...
// Looking at you, IDBMutableFile...
if (IndexedDatabaseManager::IsClosed()) {
NS_ERROR("Shouldn't be called after shutdown!");
MOZ_ASSERT(&aRefCount == &mRefCnt);
MOZ_ASSERT(aDelta == 1 || aDelta == -1);
MOZ_ASSERT(!aClear);
if (aDelta > 0) {
++aRefCount;
} else {
nsrefcnt count = --aRefCount;
if (!count) {
mRefCnt = 1;
delete this;
}
}
return;
}
MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
bool needsCleanup;
{
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
@ -117,40 +179,52 @@ FileInfo::UpdateReferences(mozilla::ThreadSafeAutoRefCnt& aRefCount,
void
FileInfo::Cleanup()
{
nsRefPtr<CleanupFileRunnable> cleaner =
new CleanupFileRunnable(mFileManager, Id());
int64_t id = Id();
// IndexedDatabaseManager is main-thread only.
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(cleaner);
nsRefPtr<CleanupFileRunnable> cleaner =
new CleanupFileRunnable(mFileManager, id);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(cleaner)));
return;
}
cleaner->Run();
CleanupFileRunnable::DoCleanup(mFileManager, id);
}
CleanupFileRunnable::CleanupFileRunnable(FileManager* aFileManager,
int64_t aFileId)
: mFileManager(aFileManager), mFileId(aFileId)
// static
void
CleanupFileRunnable::DoCleanup(FileManager* aFileManager, int64_t aFileId)
{
}
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aFileManager);
MOZ_ASSERT(aFileId > 0);
NS_IMPL_ISUPPORTS(CleanupFileRunnable,
nsIRunnable)
NS_IMETHODIMP
CleanupFileRunnable::Run()
{
if (mozilla::dom::quota::QuotaManager::IsShuttingDown()) {
return NS_OK;
if (NS_WARN_IF(QuotaManager::IsShuttingDown())) {
return;
}
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
MOZ_ASSERT(mgr);
if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, mFileId))) {
if (NS_FAILED(mgr->AsyncDeleteFile(aFileManager, aFileId))) {
NS_WARNING("Failed to delete file asynchronously!");
}
}
NS_IMPL_ISUPPORTS_INHERITED0(CleanupFileRunnable, nsRunnable)
NS_IMETHODIMP
CleanupFileRunnable::Run()
{
MOZ_ASSERT(NS_IsMainThread());
DoCleanup(mFileManager, mFileId);
return NS_OK;
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -7,112 +7,88 @@
#ifndef mozilla_dom_indexeddb_fileinfo_h__
#define mozilla_dom_indexeddb_fileinfo_h__
#include "IndexedDatabase.h"
#include "nsAutoPtr.h"
#include "nsISupportsImpl.h"
#include "FileManager.h"
#include "IndexedDatabaseManager.h"
namespace mozilla {
namespace dom {
namespace indexedDB {
BEGIN_INDEXEDDB_NAMESPACE
class FileManager;
class FileInfo
{
friend class FileManager;
public:
explicit FileInfo(FileManager* aFileManager)
: mFileManager(aFileManager)
{ }
virtual ~FileInfo()
{ }
static
FileInfo* Create(FileManager* aFileManager, int64_t aId);
void AddRef()
{
if (IndexedDatabaseManager::IsClosed()) {
++mRefCnt;
}
else {
UpdateReferences(mRefCnt, 1);
}
}
void Release()
{
if (IndexedDatabaseManager::IsClosed()) {
nsrefcnt count = --mRefCnt;
if (count == 0) {
mRefCnt = 1;
delete this;
}
}
else {
UpdateReferences(mRefCnt, -1);
}
}
void UpdateDBRefs(int32_t aDelta)
{
UpdateReferences(mDBRefCnt, aDelta);
}
void ClearDBRefs()
{
UpdateReferences(mDBRefCnt, 0, true);
}
void UpdateSliceRefs(int32_t aDelta)
{
UpdateReferences(mSliceRefCnt, aDelta);
}
void GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt,
int32_t* aSliceRefCnt);
FileManager* Manager() const
{
return mFileManager;
}
virtual int64_t Id() const = 0;
private:
void UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, int32_t aDelta,
bool aClear = false);
void Cleanup();
ThreadSafeAutoRefCnt mRefCnt;
ThreadSafeAutoRefCnt mDBRefCnt;
ThreadSafeAutoRefCnt mSliceRefCnt;
nsRefPtr<FileManager> mFileManager;
public:
static
FileInfo* Create(FileManager* aFileManager, int64_t aId);
explicit FileInfo(FileManager* aFileManager);
void
AddRef()
{
UpdateReferences(mRefCnt, 1);
}
void
Release()
{
UpdateReferences(mRefCnt, -1);
}
void
UpdateDBRefs(int32_t aDelta)
{
UpdateReferences(mDBRefCnt, aDelta);
}
void
ClearDBRefs()
{
UpdateReferences(mDBRefCnt, 0, true);
}
void
UpdateSliceRefs(int32_t aDelta)
{
UpdateReferences(mSliceRefCnt, aDelta);
}
void
GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt, int32_t* aSliceRefCnt);
FileManager*
Manager() const
{
return mFileManager;
}
virtual int64_t
Id() const = 0;
protected:
virtual ~FileInfo();
private:
void
UpdateReferences(ThreadSafeAutoRefCnt& aRefCount,
int32_t aDelta,
bool aClear = false);
void
Cleanup();
};
#define FILEINFO_SUBCLASS(_bits) \
class FileInfo##_bits : public FileInfo \
{ \
public: \
FileInfo##_bits(FileManager* aFileManager, int##_bits##_t aId) \
: FileInfo(aFileManager), mId(aId) \
{ } \
\
virtual int64_t Id() const \
{ \
return mId; \
} \
\
private: \
int##_bits##_t mId; \
};
FILEINFO_SUBCLASS(16)
FILEINFO_SUBCLASS(32)
FILEINFO_SUBCLASS(64)
#undef FILEINFO_SUBCLASS
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_fileinfo_h__

View File

@ -1,433 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FileManager.h"
#include "mozIStorageConnection.h"
#include "mozIStorageStatement.h"
#include "nsIInputStream.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/dom/quota/Utilities.h"
#include "mozStorageCID.h"
#include "mozStorageHelper.h"
#include "Client.h"
#include "FileInfo.h"
#include "IndexedDatabaseManager.h"
#include "OpenDatabaseHelper.h"
#include "IndexedDatabaseInlines.h"
#include <algorithm>
USING_INDEXEDDB_NAMESPACE
using mozilla::dom::quota::AssertIsOnIOThread;
namespace {
PLDHashOperator
EnumerateToTArray(const uint64_t& aKey,
FileInfo* aValue,
void* aUserArg)
{
NS_ASSERTION(aValue, "Null pointer!");
NS_ASSERTION(aUserArg, "Null pointer!");
nsTArray<FileInfo*>* array =
static_cast<nsTArray<FileInfo*>*>(aUserArg);
array->AppendElement(aValue);
return PL_DHASH_NEXT;
}
already_AddRefed<nsIFile>
GetDirectoryFor(const nsAString& aDirectoryPath)
{
nsCOMPtr<nsIFile> directory =
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
NS_ENSURE_TRUE(directory, nullptr);
nsresult rv = directory->InitWithPath(aDirectoryPath);
NS_ENSURE_SUCCESS(rv, nullptr);
return directory.forget();
}
} // anonymous namespace
nsresult
FileManager::Init(nsIFile* aDirectory,
mozIStorageConnection* aConnection)
{
AssertIsOnIOThread();
NS_ASSERTION(aDirectory, "Null directory!");
NS_ASSERTION(aConnection, "Null connection!");
bool exists;
nsresult rv = aDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (exists) {
bool isDirectory;
rv = aDirectory->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
}
else {
rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = aDirectory->GetPath(mDirectoryPath);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> journalDirectory;
rv = aDirectory->Clone(getter_AddRefs(journalDirectory));
NS_ENSURE_SUCCESS(rv, rv);
rv = journalDirectory->Append(NS_LITERAL_STRING(JOURNAL_DIRECTORY_NAME));
NS_ENSURE_SUCCESS(rv, rv);
rv = journalDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (exists) {
bool isDirectory;
rv = journalDirectory->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
}
rv = journalDirectory->GetPath(mJournalDirectoryPath);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageStatement> stmt;
rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT id, refcount "
"FROM file"
), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
bool hasResult;
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
int64_t id;
rv = stmt->GetInt64(0, &id);
NS_ENSURE_SUCCESS(rv, rv);
int32_t refcount;
rv = stmt->GetInt32(1, &refcount);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(refcount, "This shouldn't happen!");
nsRefPtr<FileInfo> fileInfo = FileInfo::Create(this, id);
fileInfo->mDBRefCnt = refcount;
mFileInfos.Put(id, fileInfo);
mLastFileId = std::max(id, mLastFileId);
}
return NS_OK;
}
nsresult
FileManager::Invalidate()
{
if (IndexedDatabaseManager::IsClosed()) {
NS_ERROR("Shouldn't be called after shutdown!");
return NS_ERROR_UNEXPECTED;
}
nsTArray<FileInfo*> fileInfos;
{
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
NS_ASSERTION(!mInvalidated, "Invalidate more than once?!");
mInvalidated = true;
fileInfos.SetCapacity(mFileInfos.Count());
mFileInfos.EnumerateRead(EnumerateToTArray, &fileInfos);
}
for (uint32_t i = 0; i < fileInfos.Length(); i++) {
FileInfo* fileInfo = fileInfos.ElementAt(i);
fileInfo->ClearDBRefs();
}
return NS_OK;
}
already_AddRefed<nsIFile>
FileManager::GetDirectory()
{
return GetDirectoryFor(mDirectoryPath);
}
already_AddRefed<nsIFile>
FileManager::GetJournalDirectory()
{
return GetDirectoryFor(mJournalDirectoryPath);
}
already_AddRefed<nsIFile>
FileManager::EnsureJournalDirectory()
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIFile> journalDirectory = GetDirectoryFor(mJournalDirectoryPath);
NS_ENSURE_TRUE(journalDirectory, nullptr);
bool exists;
nsresult rv = journalDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, nullptr);
if (exists) {
bool isDirectory;
rv = journalDirectory->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, nullptr);
NS_ENSURE_TRUE(isDirectory, nullptr);
}
else {
rv = journalDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755);
NS_ENSURE_SUCCESS(rv, nullptr);
}
return journalDirectory.forget();
}
already_AddRefed<FileInfo>
FileManager::GetFileInfo(int64_t aId)
{
if (IndexedDatabaseManager::IsClosed()) {
NS_ERROR("Shouldn't be called after shutdown!");
return nullptr;
}
FileInfo* fileInfo = nullptr;
{
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
fileInfo = mFileInfos.Get(aId);
}
nsRefPtr<FileInfo> result = fileInfo;
return result.forget();
}
already_AddRefed<FileInfo>
FileManager::GetNewFileInfo()
{
if (IndexedDatabaseManager::IsClosed()) {
NS_ERROR("Shouldn't be called after shutdown!");
return nullptr;
}
nsAutoPtr<FileInfo> fileInfo;
{
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
int64_t id = mLastFileId + 1;
fileInfo = FileInfo::Create(this, id);
mFileInfos.Put(id, fileInfo);
mLastFileId = id;
}
nsRefPtr<FileInfo> result = fileInfo.forget();
return result.forget();
}
// static
already_AddRefed<nsIFile>
FileManager::GetFileForId(nsIFile* aDirectory, int64_t aId)
{
NS_ASSERTION(aDirectory, "Null pointer!");
nsAutoString id;
id.AppendInt(aId);
nsCOMPtr<nsIFile> file;
nsresult rv = aDirectory->Clone(getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, nullptr);
rv = file->Append(id);
NS_ENSURE_SUCCESS(rv, nullptr);
return file.forget();
}
// static
nsresult
FileManager::InitDirectory(nsIFile* aDirectory,
nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin)
{
AssertIsOnIOThread();
NS_ASSERTION(aDirectory, "Null directory!");
NS_ASSERTION(aDatabaseFile, "Null database file!");
bool exists;
nsresult rv = aDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (!exists) {
return NS_OK;
}
bool isDirectory;
rv = aDirectory->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
nsCOMPtr<nsIFile> journalDirectory;
rv = aDirectory->Clone(getter_AddRefs(journalDirectory));
NS_ENSURE_SUCCESS(rv, rv);
rv = journalDirectory->Append(NS_LITERAL_STRING(JOURNAL_DIRECTORY_NAME));
NS_ENSURE_SUCCESS(rv, rv);
rv = journalDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (exists) {
rv = journalDirectory->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
nsCOMPtr<nsISimpleEnumerator> entries;
rv = journalDirectory->GetDirectoryEntries(getter_AddRefs(entries));
NS_ENSURE_SUCCESS(rv, rv);
bool hasElements;
rv = entries->HasMoreElements(&hasElements);
NS_ENSURE_SUCCESS(rv, rv);
if (hasElements) {
nsCOMPtr<mozIStorageConnection> connection;
rv = OpenDatabaseHelper::CreateDatabaseConnection(aDatabaseFile,
aDirectory, NullString(), aPersistenceType, aGroup, aOrigin,
getter_AddRefs(connection));
NS_ENSURE_SUCCESS(rv, rv);
mozStorageTransaction transaction(connection, false);
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE VIRTUAL TABLE fs USING filesystem;"
));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageStatement> stmt;
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT name, (name IN (SELECT id FROM file)) FROM fs "
"WHERE path = :path"
), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
nsString path;
rv = journalDirectory->GetPath(path);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("path"), path);
NS_ENSURE_SUCCESS(rv, rv);
bool hasResult;
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
nsString name;
rv = stmt->GetString(0, name);
NS_ENSURE_SUCCESS(rv, rv);
int32_t flag = stmt->AsInt32(1);
if (!flag) {
nsCOMPtr<nsIFile> file;
rv = aDirectory->Clone(getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
rv = file->Append(name);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(file->Remove(false))) {
NS_WARNING("Failed to remove orphaned file!");
}
}
nsCOMPtr<nsIFile> journalFile;
rv = journalDirectory->Clone(getter_AddRefs(journalFile));
NS_ENSURE_SUCCESS(rv, rv);
rv = journalFile->Append(name);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(journalFile->Remove(false))) {
NS_WARNING("Failed to remove journal file!");
}
}
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE fs;"
));
NS_ENSURE_SUCCESS(rv, rv);
transaction.Commit();
}
}
return NS_OK;
}
// static
nsresult
FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage)
{
AssertIsOnIOThread();
bool exists;
nsresult rv = aDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (!exists) {
*aUsage = 0;
return NS_OK;
}
nsCOMPtr<nsISimpleEnumerator> entries;
rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
NS_ENSURE_SUCCESS(rv, rv);
uint64_t usage = 0;
bool hasMore;
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
nsCOMPtr<nsISupports> entry;
rv = entries->GetNext(getter_AddRefs(entry));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
NS_ENSURE_TRUE(file, NS_NOINTERFACE);
nsString leafName;
rv = file->GetLeafName(leafName);
NS_ENSURE_SUCCESS(rv, rv);
if (leafName.EqualsLiteral(JOURNAL_DIRECTORY_NAME)) {
continue;
}
int64_t fileSize;
rv = file->GetFileSize(&fileSize);
NS_ENSURE_SUCCESS(rv, rv);
quota::IncrementUsage(&usage, uint64_t(fileSize));
}
*aUsage = usage;
return NS_OK;
}

View File

@ -7,21 +7,23 @@
#ifndef mozilla_dom_indexeddb_filemanager_h__
#define mozilla_dom_indexeddb_filemanager_h__
#include "IndexedDatabase.h"
#include "nsIDOMFile.h"
#include "nsIFile.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/StoragePrivilege.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsISupportsImpl.h"
class nsIFile;
class mozIStorageConnection;
BEGIN_INDEXEDDB_NAMESPACE
namespace mozilla {
namespace dom {
namespace indexedDB {
class FileInfo;
// Implemented in ActorsParent.cpp.
class FileManager MOZ_FINAL
{
friend class FileInfo;
@ -29,79 +31,6 @@ class FileManager MOZ_FINAL
typedef mozilla::dom::quota::PersistenceType PersistenceType;
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
public:
FileManager(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin, StoragePrivilege aPrivilege,
const nsAString& aDatabaseName)
: mPersistenceType(aPersistenceType), mGroup(aGroup), mOrigin(aOrigin),
mPrivilege(aPrivilege), mDatabaseName(aDatabaseName), mLastFileId(0),
mInvalidated(false)
{ }
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileManager)
PersistenceType Type()
{
return mPersistenceType;
}
const nsACString& Group() const
{
return mGroup;
}
const nsACString& Origin() const
{
return mOrigin;
}
const StoragePrivilege& Privilege() const
{
return mPrivilege;
}
const nsAString& DatabaseName() const
{
return mDatabaseName;
}
bool Invalidated() const
{
return mInvalidated;
}
nsresult Init(nsIFile* aDirectory,
mozIStorageConnection* aConnection);
nsresult Invalidate();
already_AddRefed<nsIFile> GetDirectory();
already_AddRefed<nsIFile> GetJournalDirectory();
already_AddRefed<nsIFile> EnsureJournalDirectory();
already_AddRefed<FileInfo> GetFileInfo(int64_t aId);
already_AddRefed<FileInfo> GetNewFileInfo();
static already_AddRefed<nsIFile> GetFileForId(nsIFile* aDirectory,
int64_t aId);
static nsresult InitDirectory(nsIFile* aDirectory,
nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin);
static nsresult GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
private:
// Private destructor, to discourage deletion outside of Release():
~FileManager()
{
}
PersistenceType mPersistenceType;
nsCString mGroup;
nsCString mOrigin;
@ -117,8 +46,92 @@ private:
nsDataHashtable<nsUint64HashKey, FileInfo*> mFileInfos;
bool mInvalidated;
public:
static already_AddRefed<nsIFile>
GetFileForId(nsIFile* aDirectory, int64_t aId);
static nsresult
InitDirectory(nsIFile* aDirectory,
nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin);
static nsresult
GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
FileManager(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
StoragePrivilege aPrivilege,
const nsAString& aDatabaseName);
PersistenceType
Type() const
{
return mPersistenceType;
}
const nsACString&
Group() const
{
return mGroup;
}
const nsACString&
Origin() const
{
return mOrigin;
}
const StoragePrivilege&
Privilege() const
{
return mPrivilege;
}
const nsAString&
DatabaseName() const
{
return mDatabaseName;
}
bool
Invalidated() const
{
return mInvalidated;
}
nsresult
Init(nsIFile* aDirectory, mozIStorageConnection* aConnection);
nsresult
Invalidate();
already_AddRefed<nsIFile>
GetDirectory();
already_AddRefed<nsIFile>
GetJournalDirectory();
already_AddRefed<nsIFile>
EnsureJournalDirectory();
already_AddRefed<FileInfo>
GetFileInfo(int64_t aId);
already_AddRefed<FileInfo>
GetNewFileInfo();
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileManager)
private:
~FileManager();
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_filemanager_h__

View File

@ -7,39 +7,56 @@
#include "FileSnapshot.h"
#include "IDBFileHandle.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "nsDebug.h"
#include "mozilla/dom/MetadataHelper.h"
#ifdef DEBUG
#include "nsXULAppAPI.h"
#endif
namespace mozilla {
namespace dom {
namespace indexedDB {
NS_IMPL_ISUPPORTS_INHERITED0(FileImplSnapshot, DOMFileImpl)
// Create as a stored file
FileImplSnapshot::FileImplSnapshot(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile,
MetadataParameters* aMetadataParams,
nsIFile* aFile,
IDBFileHandle* aFileHandle,
FileInfo* aFileInfo)
: DOMFileImplBase(aName, aContentType, aLength),
mFile(aFile), mFileHandle(aFileHandle), mWholeFile(true)
: DOMFileImplBase(aName,
aContentType,
aMetadataParams->Size(),
aMetadataParams->LastModified())
, mFile(aFile)
, mFileHandle(aFileHandle)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "Null file!");
MOZ_ASSERT(mFileHandle, "Null file handle!");
AssertSanity();
MOZ_ASSERT(aMetadataParams);
MOZ_ASSERT(aMetadataParams->Size() != UINT64_MAX);
MOZ_ASSERT(aMetadataParams->LastModified() != INT64_MAX);
MOZ_ASSERT(aFile);
MOZ_ASSERT(aFileHandle);
MOZ_ASSERT(aFileInfo);
mFileInfos.AppendElement(aFileInfo);
}
// Create slice
FileImplSnapshot::FileImplSnapshot(const FileImplSnapshot* aOther,
uint64_t aStart, uint64_t aLength,
uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType)
: DOMFileImplBase(aContentType, aOther->mStart + aStart, aLength),
mFile(aOther->mFile), mFileHandle(aOther->mFileHandle),
mWholeFile(false)
: DOMFileImplBase(aContentType, aOther->mStart + aStart, aLength)
, mFile(aOther->mFile)
, mFileHandle(aOther->mFileHandle)
, mWholeFile(false)
{
MOZ_ASSERT(mFile, "Null file!");
MOZ_ASSERT(mFileHandle, "Null file handle!");
AssertSanity();
MOZ_ASSERT(aOther);
FileInfo* fileInfo;
@ -57,9 +74,25 @@ FileImplSnapshot::~FileImplSnapshot()
{
}
#ifdef DEBUG
// static
void
FileImplSnapshot::AssertSanity()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread());
}
#endif // DEBUG
NS_IMPL_ISUPPORTS_INHERITED0(FileImplSnapshot, DOMFileImpl)
void
FileImplSnapshot::Unlink()
{
AssertSanity();
FileImplSnapshot* tmp = this;
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFileHandle);
}
@ -67,43 +100,80 @@ FileImplSnapshot::Unlink()
void
FileImplSnapshot::Traverse(nsCycleCollectionTraversalCallback &cb)
{
AssertSanity();
FileImplSnapshot* tmp = this;
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileHandle);
}
bool
FileImplSnapshot::IsCCed() const
{
AssertSanity();
return true;
}
nsresult
FileImplSnapshot::GetInternalStream(nsIInputStream** aStream)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertSanity();
nsresult rv = mFileHandle->OpenInputStream(mWholeFile, mStart, mLength,
aStream);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
already_AddRefed<nsIDOMBlob>
FileImplSnapshot::CreateSlice(uint64_t aStart, uint64_t aLength,
already_AddRefed<DOMFileImpl>
FileImplSnapshot::CreateSlice(uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertSanity();
nsCOMPtr<nsIDOMBlob> t =
new DOMFile(new FileImplSnapshot(this, aStart, aLength, aContentType));
nsRefPtr<DOMFileImpl> impl =
new FileImplSnapshot(this, aStart, aLength, aContentType);
return t.forget();
return impl.forget();
}
nsresult
FileImplSnapshot::GetMozFullPathInternal(nsAString& aFilename)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(mIsFile, "Should only be called on files");
AssertSanity();
MOZ_ASSERT(mIsFile);
return mFile->GetPath(aFilename);
}
bool
FileImplSnapshot::IsStoredFile() const
{
AssertSanity();
return true;
}
bool
FileImplSnapshot::IsWholeFile() const
{
AssertSanity();
return mWholeFile;
}
bool
FileImplSnapshot::IsSnapshot() const
{
AssertSanity();
return true;
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -10,26 +10,55 @@
#include "mozilla/Attributes.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsDOMFile.h"
namespace mozilla {
namespace dom {
class MetadataParameters;
namespace indexedDB {
class IDBFileHandle;
class FileImplSnapshot : public DOMFileImplBase
class FileImplSnapshot MOZ_FINAL
: public DOMFileImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
typedef mozilla::dom::MetadataParameters MetadataParameters;
nsCOMPtr<nsIFile> mFile;
nsRefPtr<IDBFileHandle> mFileHandle;
bool mWholeFile;
public:
// Create as a stored file
FileImplSnapshot(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile, IDBFileHandle* aFileHandle,
FileImplSnapshot(const nsAString& aName,
const nsAString& aContentType,
MetadataParameters* aMetadataParams,
nsIFile* aFile,
IDBFileHandle* aFileHandle,
FileInfo* aFileInfo);
// Overrides
NS_DECL_ISUPPORTS_INHERITED
private:
// Create slice
FileImplSnapshot(const FileImplSnapshot* aOther,
uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType);
~FileImplSnapshot();
static void
AssertSanity()
#ifdef DEBUG
;
#else
{ }
#endif
virtual nsresult
GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
@ -43,45 +72,21 @@ public:
Traverse(nsCycleCollectionTraversalCallback &aCb) MOZ_OVERRIDE;
virtual bool
IsCCed() const MOZ_OVERRIDE
{
return true;
}
IsCCed() const MOZ_OVERRIDE;
protected:
// Create slice
FileImplSnapshot(const FileImplSnapshot* aOther, uint64_t aStart,
uint64_t aLength, const nsAString& aContentType);
virtual ~FileImplSnapshot();
virtual already_AddRefed<nsIDOMBlob>
CreateSlice(uint64_t aStart, uint64_t aLength,
virtual already_AddRefed<DOMFileImpl>
CreateSlice(uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType) MOZ_OVERRIDE;
virtual bool
IsStoredFile() const MOZ_OVERRIDE
{
return true;
}
IsStoredFile() const MOZ_OVERRIDE;
virtual bool
IsWholeFile() const MOZ_OVERRIDE
{
return mWholeFile;
}
IsWholeFile() const MOZ_OVERRIDE;
virtual bool
IsSnapshot() const MOZ_OVERRIDE
{
return true;
}
private:
nsCOMPtr<nsIFile> mFile;
nsRefPtr<IDBFileHandle> mFileHandle;
bool mWholeFile;
IsSnapshot() const MOZ_OVERRIDE;
};
} // namespace indexedDB

File diff suppressed because it is too large Load Diff

View File

@ -7,59 +7,38 @@
#ifndef mozilla_dom_indexeddb_idbcursor_h__
#define mozilla_dom_indexeddb_idbcursor_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "IndexedDatabase.h"
#include "js/RootingAPI.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/IDBCursorBinding.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/indexedDB/Key.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/indexedDB/Key.h"
class nsIRunnable;
class nsIScriptContext;
class nsPIDOMWindow;
namespace mozilla {
class ErrorResult;
namespace dom {
class OwningIDBObjectStoreOrIDBIndex;
}
}
BEGIN_INDEXEDDB_NAMESPACE
namespace indexedDB {
class ContinueHelper;
class ContinueObjectStoreHelper;
class ContinueIndexHelper;
class ContinueIndexObjectHelper;
class BackgroundCursorChild;
class IDBIndex;
class IDBObjectStore;
class IDBRequest;
class IDBTransaction;
class IndexedDBCursorChild;
class IndexedDBCursorParent;
class IDBCursor MOZ_FINAL : public nsISupports,
public nsWrapperCache
class IDBCursor MOZ_FINAL
: public nsISupports
, public nsWrapperCache
{
friend class ContinueHelper;
friend class ContinueObjectStoreHelper;
friend class ContinueIndexHelper;
friend class ContinueIndexObjectHelper;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
enum Type
{
OBJECTSTORE = 0,
OBJECTSTOREKEY,
INDEXKEY,
INDEXOBJECT
};
enum Direction
{
NEXT = 0,
@ -71,112 +50,84 @@ public:
DIRECTION_INVALID
};
// For OBJECTSTORE cursors.
static
already_AddRefed<IDBCursor>
Create(IDBRequest* aRequest,
IDBTransaction* aTransaction,
IDBObjectStore* aObjectStore,
Direction aDirection,
const Key& aRangeKey,
const nsACString& aContinueQuery,
const nsACString& aContinueToQuery,
const Key& aKey,
StructuredCloneReadInfo&& aCloneReadInfo);
private:
enum Type
{
Type_ObjectStore,
Type_ObjectStoreKey,
Type_Index,
Type_IndexKey,
};
// For OBJECTSTOREKEY cursors.
static
already_AddRefed<IDBCursor>
Create(IDBRequest* aRequest,
IDBTransaction* aTransaction,
IDBObjectStore* aObjectStore,
nsRefPtr<IDBObjectStore> mSourceObjectStore;
nsRefPtr<IDBIndex> mSourceIndex;
nsRefPtr<IDBTransaction> mTransaction;
BackgroundCursorChild* mBackgroundActor;
JS::Heap<JSObject*> mScriptOwner;
// These are cycle-collected!
JS::Heap<JS::Value> mCachedKey;
JS::Heap<JS::Value> mCachedPrimaryKey;
JS::Heap<JS::Value> mCachedValue;
Key mKey;
Key mPrimaryKey;
StructuredCloneReadInfo mCloneInfo;
const Type mType;
const Direction mDirection;
bool mHaveCachedKey : 1;
bool mHaveCachedPrimaryKey : 1;
bool mHaveCachedValue : 1;
bool mRooted : 1;
bool mContinueCalled : 1;
bool mHaveValue : 1;
public:
static already_AddRefed<IDBCursor>
Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aKey,
StructuredCloneReadInfo&& aCloneInfo);
static already_AddRefed<IDBCursor>
Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aRangeKey,
const nsACString& aContinueQuery,
const nsACString& aContinueToQuery,
const Key& aKey);
// For INDEXKEY cursors.
static
already_AddRefed<IDBCursor>
Create(IDBRequest* aRequest,
IDBTransaction* aTransaction,
IDBIndex* aIndex,
static already_AddRefed<IDBCursor>
Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aRangeKey,
const nsACString& aContinueQuery,
const nsACString& aContinueToQuery,
const Key& aKey,
const Key& aObjectKey);
const Key& aPrimaryKey,
StructuredCloneReadInfo&& aCloneInfo);
// For INDEXOBJECT cursors.
static
already_AddRefed<IDBCursor>
Create(IDBRequest* aRequest,
IDBTransaction* aTransaction,
IDBIndex* aIndex,
static already_AddRefed<IDBCursor>
Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aRangeKey,
const nsACString& aContinueQuery,
const nsACString& aContinueToQuery,
const Key& aKey,
const Key& aObjectKey,
StructuredCloneReadInfo&& aCloneReadInfo);
IDBTransaction* Transaction() const
{
return mTransaction;
}
IDBRequest* Request() const
{
return mRequest;
}
const Key& aPrimaryKey);
static Direction
ConvertDirection(IDBCursorDirection aDirection);
void
SetActor(IndexedDBCursorChild* aActorChild)
{
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
mActorChild = aActorChild;
}
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
void
SetActor(IndexedDBCursorParent* aActorParent)
{
NS_ASSERTION(!aActorParent || !mActorParent,
"Shouldn't have more than one!");
mActorParent = aActorParent;
}
IndexedDBCursorChild*
GetActorChild() const
{
return mActorChild;
}
IndexedDBCursorParent*
GetActorParent() const
{
return mActorParent;
}
void
ContinueInternal(const Key& aKey, int32_t aCount,
ErrorResult& aRv);
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
IDBTransaction*
GetParentObject() const
{
return mTransaction;
}
nsPIDOMWindow*
GetParentObject() const;
void
GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const;
@ -185,80 +136,79 @@ public:
GetDirection() const;
void
GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
GetKey(JSContext* aCx,
JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv);
void
GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
GetPrimaryKey(JSContext* aCx,
JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
void
GetValue(JSContext* aCx,
JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv);
void
Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
void
Advance(uint32_t aCount, ErrorResult& aRv);
void
Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
already_AddRefed<IDBRequest>
Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
already_AddRefed<IDBRequest>
Delete(JSContext* aCx, ErrorResult& aRv);
void
GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv);
Reset();
void
Reset(Key&& aKey, StructuredCloneReadInfo&& aValue);
void
Reset(Key&& aKey);
void
Reset(Key&& aKey, Key&& aPrimaryKey, StructuredCloneReadInfo&& aValue);
void
Reset(Key&& aKey, Key&& aPrimaryKey);
void
ClearBackgroundActor()
{
AssertIsOnOwningThread();
mBackgroundActor = nullptr;
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
private:
IDBCursor(Type aType,
IDBObjectStore* aSourceObjectStore,
IDBIndex* aSourceIndex,
IDBTransaction* aTransaction,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aKey);
protected:
IDBCursor();
~IDBCursor();
void DropJSObjects();
static
already_AddRefed<IDBCursor>
CreateCommon(IDBRequest* aRequest,
IDBTransaction* aTransaction,
IDBObjectStore* aObjectStore,
Direction aDirection,
const Key& aRangeKey,
const nsACString& aContinueQuery,
const nsACString& aContinueToQuery);
nsRefPtr<IDBRequest> mRequest;
nsRefPtr<IDBTransaction> mTransaction;
nsRefPtr<IDBObjectStore> mObjectStore;
nsRefPtr<IDBIndex> mIndex;
JS::Heap<JSObject*> mScriptOwner;
Type mType;
Direction mDirection;
nsCString mContinueQuery;
nsCString mContinueToQuery;
// These are cycle-collected!
JS::Heap<JS::Value> mCachedKey;
JS::Heap<JS::Value> mCachedPrimaryKey;
JS::Heap<JS::Value> mCachedValue;
Key mRangeKey;
Key mKey;
Key mObjectKey;
StructuredCloneReadInfo mCloneReadInfo;
Key mContinueToKey;
IndexedDBCursorChild* mActorChild;
IndexedDBCursorParent* mActorParent;
bool mHaveCachedKey;
bool mHaveCachedPrimaryKey;
bool mHaveCachedValue;
bool mRooted;
bool mContinueCalled;
bool mHaveValue;
void
DropJSObjects();
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbcursor_h__

File diff suppressed because it is too large Load Diff

View File

@ -7,274 +7,302 @@
#ifndef mozilla_dom_indexeddb_idbdatabase_h__
#define mozilla_dom_indexeddb_idbdatabase_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "nsIDocument.h"
#include "nsIOfflineStorage.h"
#include "mozilla/Attributes.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/IDBObjectStoreBinding.h"
#include "mozilla/dom/IDBTransactionBinding.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/indexedDB/FileManager.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "mozilla/dom/StorageTypeBinding.h"
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "nsAutoPtr.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsString.h"
#include "nsTHashtable.h"
class nsIScriptContext;
class nsIDocument;
class nsIDOMBlob;
class nsIWeakReference;
class nsPIDOMWindow;
namespace mozilla {
class ErrorResult;
class EventChainPostVisitor;
namespace dom {
class nsIContentParent;
namespace quota {
class Client;
}
}
}
BEGIN_INDEXEDDB_NAMESPACE
class DOMStringList;
struct IDBObjectStoreParameters;
template <typename> class Sequence;
class AsyncConnectionHelper;
struct DatabaseInfo;
namespace indexedDB {
class BackgroundDatabaseChild;
class DatabaseSpec;
class FileManager;
class IDBFactory;
class IDBIndex;
class IDBMutableFile;
class IDBObjectStore;
class IDBRequest;
class IDBTransaction;
class IndexedDatabaseManager;
class IndexedDBDatabaseChild;
class IndexedDBDatabaseParent;
struct ObjectStoreInfoGuts;
class PBackgroundIDBDatabaseFileChild;
class IDBDatabase MOZ_FINAL : public IDBWrapperCache,
public nsIOfflineStorage
class IDBDatabase MOZ_FINAL
: public IDBWrapperCache
{
friend class AsyncConnectionHelper;
friend class IndexedDatabaseManager;
friend class IndexedDBDatabaseParent;
friend class IndexedDBDatabaseChild;
typedef mozilla::dom::StorageType StorageType;
typedef mozilla::dom::quota::PersistenceType PersistenceType;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIOFFLINESTORAGE
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, IDBWrapperCache)
static already_AddRefed<IDBDatabase>
Create(IDBWrapperCache* aOwnerCache,
IDBFactory* aFactory,
already_AddRefed<DatabaseInfo> aDatabaseInfo,
const nsACString& aASCIIOrigin,
FileManager* aFileManager,
mozilla::dom::nsIContentParent* aContentParent);
static IDBDatabase*
FromStorage(nsIOfflineStorage* aStorage);
// nsIDOMEventTarget
virtual nsresult PostHandleEvent(
EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
DatabaseInfo* Info() const
{
return mDatabaseInfo;
}
const nsString& Name() const
{
return mName;
}
const nsString& FilePath() const
{
return mFilePath;
}
already_AddRefed<nsIDocument> GetOwnerDocument()
{
if (!GetOwner()) {
return nullptr;
}
nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
return doc.forget();
}
// Whether or not the database has been invalidated. If it has then no further
// transactions for this database will be allowed to run. This function may be
// called on any thread.
bool IsInvalidated() const
{
return mInvalidated;
}
void DisconnectFromActorParent();
void CloseInternal(bool aIsDead);
void EnterSetVersionTransaction();
void ExitSetVersionTransaction();
// Called when a versionchange transaction is aborted to reset the
// DatabaseInfo.
void RevertToPreviousState();
FileManager* Manager() const
{
return mFileManager;
}
void
SetActor(IndexedDBDatabaseChild* aActorChild)
{
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
mActorChild = aActorChild;
}
void
SetActor(IndexedDBDatabaseParent* aActorParent)
{
NS_ASSERTION(!aActorParent || !mActorParent,
"Shouldn't have more than one!");
mActorParent = aActorParent;
}
IndexedDBDatabaseChild*
GetActorChild() const
{
return mActorChild;
}
IndexedDBDatabaseParent*
GetActorParent() const
{
return mActorParent;
}
mozilla::dom::nsIContentParent*
GetContentParent() const
{
return mContentParent;
}
already_AddRefed<IDBObjectStore>
CreateObjectStoreInternal(IDBTransaction* aTransaction,
const ObjectStoreInfoGuts& aInfo,
ErrorResult& aRv);
IDBFactory*
Factory() const
{
return mFactory;
}
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
nsPIDOMWindow*
GetParentObject() const
{
return GetOwner();
}
void
GetName(nsString& aName) const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
aName.Assign(mName);
}
uint64_t
Version() const;
already_AddRefed<mozilla::dom::DOMStringList>
GetObjectStoreNames(ErrorResult& aRv) const;
already_AddRefed<IDBObjectStore>
CreateObjectStore(JSContext* aCx, const nsAString& aName,
const IDBObjectStoreParameters& aOptionalParameters,
ErrorResult& aRv);
void
DeleteObjectStore(const nsAString& name, ErrorResult& aRv);
already_AddRefed<indexedDB::IDBTransaction>
Transaction(const nsAString& aStoreName, IDBTransactionMode aMode,
ErrorResult& aRv)
{
Sequence<nsString> list;
list.AppendElement(aStoreName);
return Transaction(list, aMode, aRv);
}
already_AddRefed<indexedDB::IDBTransaction>
Transaction(const Sequence<nsString>& aStoreNames, IDBTransactionMode aMode,
ErrorResult& aRv);
IMPL_EVENT_HANDLER(abort)
IMPL_EVENT_HANDLER(error)
IMPL_EVENT_HANDLER(versionchange)
mozilla::dom::StorageType
Storage() const
{
return PersistenceTypeToStorage(mPersistenceType);
}
already_AddRefed<IDBRequest>
CreateMutableFile(const nsAString& aName, const Optional<nsAString>& aType,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
MozCreateFileHandle(const nsAString& aName, const Optional<nsAString>& aType,
ErrorResult& aRv)
{
return CreateMutableFile(aName, aType, aRv);
}
virtual void LastRelease() MOZ_OVERRIDE;
private:
explicit IDBDatabase(IDBWrapperCache* aOwnerCache);
~IDBDatabase();
void OnUnlink();
void InvalidateInternal(bool aIsDead);
class Observer;
friend class Observer;
// The factory must be kept alive when IndexedDB is used in multiple
// processes. If it dies then the entire actor tree will be destroyed with it
// and the world will explode.
nsRefPtr<IDBFactory> mFactory;
nsRefPtr<DatabaseInfo> mDatabaseInfo;
nsAutoPtr<DatabaseSpec> mSpec;
// Set to a copy of the existing DatabaseInfo when starting a versionchange
// transaction.
nsRefPtr<DatabaseInfo> mPreviousDatabaseInfo;
nsCString mDatabaseId;
nsString mName;
nsString mFilePath;
nsCString mASCIIOrigin;
// Normally null except during a versionchange transaction.
nsAutoPtr<DatabaseSpec> mPreviousSpec;
nsRefPtr<FileManager> mFileManager;
IndexedDBDatabaseChild* mActorChild;
IndexedDBDatabaseParent* mActorParent;
BackgroundDatabaseChild* mBackgroundActor;
mozilla::dom::nsIContentParent* mContentParent;
nsTHashtable<nsPtrHashKey<IDBTransaction>> mTransactions;
nsRefPtr<mozilla::dom::quota::Client> mQuotaClient;
nsDataHashtable<nsISupportsHashKey, PBackgroundIDBDatabaseFileChild*>
mFileActors;
nsTHashtable<nsISupportsHashKey> mReceivedBlobs;
nsRefPtr<Observer> mObserver;
// Weak refs, IDBMutableFile strongly owns this IDBDatabase object.
nsTArray<IDBMutableFile*> mLiveMutableFiles;
bool mInvalidated;
bool mRegistered;
bool mClosed;
bool mRunningVersionChange;
bool mInvalidated;
public:
static already_AddRefed<IDBDatabase>
Create(IDBWrapperCache* aOwnerCache,
IDBFactory* aFactory,
BackgroundDatabaseChild* aActor,
DatabaseSpec* aSpec);
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
const nsString&
Name() const;
void
GetName(nsAString& aName) const
{
AssertIsOnOwningThread();
aName = Name();
}
uint64_t
Version() const;
already_AddRefed<nsIDocument>
GetOwnerDocument() const;
void
Close()
{
AssertIsOnOwningThread();
CloseInternal();
}
bool
IsClosed() const
{
AssertIsOnOwningThread();
return mClosed;
}
void
Invalidate();
// Whether or not the database has been invalidated. If it has then no further
// transactions for this database will be allowed to run.
bool
IsInvalidated() const
{
AssertIsOnOwningThread();
return mInvalidated;
}
void
EnterSetVersionTransaction(uint64_t aNewVersion);
void
ExitSetVersionTransaction();
// Called when a versionchange transaction is aborted to reset the
// DatabaseInfo.
void
RevertToPreviousState();
IDBFactory*
Factory() const
{
AssertIsOnOwningThread();
return mFactory;
}
void
RegisterTransaction(IDBTransaction* aTransaction);
void
UnregisterTransaction(IDBTransaction* aTransaction);
void
AbortTransactions();
PBackgroundIDBDatabaseFileChild*
GetOrCreateFileActorForBlob(nsIDOMBlob* aBlob);
void
NoteFinishedFileActor(PBackgroundIDBDatabaseFileChild* aFileActor);
void
NoteReceivedBlob(nsIDOMBlob* aBlob);
void
DelayedMaybeExpireFileActors();
// XXX This doesn't really belong here... It's only needed for IDBMutableFile
// serialization and should be removed someday.
nsresult
GetQuotaInfo(nsACString& aOrigin, PersistenceType* aPersistenceType);
void
NoteLiveMutableFile(IDBMutableFile* aMutableFile);
void
NoteFinishedMutableFile(IDBMutableFile* aMutableFile);
nsPIDOMWindow*
GetParentObject() const;
already_AddRefed<DOMStringList>
ObjectStoreNames() const;
already_AddRefed<IDBObjectStore>
CreateObjectStore(JSContext* aCx,
const nsAString& aName,
const IDBObjectStoreParameters& aOptionalParameters,
ErrorResult& aRv);
void
DeleteObjectStore(const nsAString& name, ErrorResult& aRv);
already_AddRefed<IDBTransaction>
Transaction(const nsAString& aStoreName,
IDBTransactionMode aMode,
ErrorResult& aRv);
already_AddRefed<IDBTransaction>
Transaction(const Sequence<nsString>& aStoreNames,
IDBTransactionMode aMode,
ErrorResult& aRv);
StorageType
Storage() const;
IMPL_EVENT_HANDLER(abort)
IMPL_EVENT_HANDLER(error)
IMPL_EVENT_HANDLER(versionchange)
already_AddRefed<IDBRequest>
CreateMutableFile(const nsAString& aName,
const Optional<nsAString>& aType,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
MozCreateFileHandle(const nsAString& aName,
const Optional<nsAString>& aType,
ErrorResult& aRv)
{
return CreateMutableFile(aName, aType, aRv);
}
void
ClearBackgroundActor()
{
AssertIsOnOwningThread();
mBackgroundActor = nullptr;
}
const DatabaseSpec*
Spec() const
{
return mSpec;
}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, IDBWrapperCache)
// nsIDOMEventTarget
virtual void
LastRelease() MOZ_OVERRIDE;
virtual nsresult
PostHandleEvent(EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
private:
IDBDatabase(IDBWrapperCache* aOwnerCache,
IDBFactory* aFactory,
BackgroundDatabaseChild* aActor,
DatabaseSpec* aSpec);
~IDBDatabase();
void
CloseInternal();
void
InvalidateInternal();
bool
RunningVersionChangeTransaction() const
{
AssertIsOnOwningThread();
return !!mPreviousSpec;
}
void
RefreshSpec(bool aMayDelete);
void
ExpireFileActors(bool aExpireAll);
void
InvalidateMutableFiles();
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbdatabase_h__

View File

@ -6,49 +6,45 @@
#include "IDBEvents.h"
#include "nsJSON.h"
#include "nsThreadUtils.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/IDBVersionChangeEventBinding.h"
#include "nsString.h"
#include "IDBRequest.h"
#include "IDBTransaction.h"
USING_INDEXEDDB_NAMESPACE
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::indexedDB;
namespace {
namespace mozilla {
namespace dom {
namespace indexedDB {
class EventFiringRunnable : public nsRunnable
{
public:
EventFiringRunnable(EventTarget* aTarget,
nsIDOMEvent* aEvent)
: mTarget(aTarget), mEvent(aEvent)
{ }
NS_IMETHOD Run() {
bool dummy;
return mTarget->DispatchEvent(mEvent, &dummy);
}
private:
nsCOMPtr<EventTarget> mTarget;
nsCOMPtr<nsIDOMEvent> mEvent;
};
} // anonymous namespace
const char16_t* kAbortEventType = MOZ_UTF16("abort");
const char16_t* kBlockedEventType = MOZ_UTF16("blocked");
const char16_t* kCompleteEventType = MOZ_UTF16("complete");
const char16_t* kErrorEventType = MOZ_UTF16("error");
const char16_t* kSuccessEventType = MOZ_UTF16("success");
const char16_t* kUpgradeNeededEventType = MOZ_UTF16("upgradeneeded");
const char16_t* kVersionChangeEventType = MOZ_UTF16("versionchange");
already_AddRefed<nsIDOMEvent>
mozilla::dom::indexedDB::CreateGenericEvent(mozilla::dom::EventTarget* aOwner,
const nsAString& aType,
Bubbles aBubbles,
Cancelable aCancelable)
CreateGenericEvent(EventTarget* aOwner,
const nsDependentString& aType,
Bubbles aBubbles,
Cancelable aCancelable)
{
nsCOMPtr<nsIDOMEvent> event;
NS_NewDOMEvent(getter_AddRefs(event), aOwner, nullptr, nullptr);
nsresult rv = event->InitEvent(aType,
aBubbles == eDoesBubble ? true : false,
aCancelable == eCancelable ? true : false);
NS_ENSURE_SUCCESS(rv, nullptr);
nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), aOwner, nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
rv = event->InitEvent(aType,
aBubbles == eDoesBubble ? true : false,
aCancelable == eCancelable ? true : false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
event->SetTrusted(true);
@ -57,37 +53,39 @@ mozilla::dom::indexedDB::CreateGenericEvent(mozilla::dom::EventTarget* aOwner,
// static
already_AddRefed<IDBVersionChangeEvent>
IDBVersionChangeEvent::CreateInternal(mozilla::dom::EventTarget* aOwner,
IDBVersionChangeEvent::CreateInternal(EventTarget* aOwner,
const nsAString& aType,
uint64_t aOldVersion,
uint64_t aNewVersion)
Nullable<uint64_t> aNewVersion)
{
nsRefPtr<IDBVersionChangeEvent> event(new IDBVersionChangeEvent(aOwner));
nsRefPtr<IDBVersionChangeEvent> event =
new IDBVersionChangeEvent(aOwner, aOldVersion);
if (!aNewVersion.IsNull()) {
event->mNewVersion.SetValue(aNewVersion.Value());
}
nsresult rv = event->InitEvent(aType, false, false);
NS_ENSURE_SUCCESS(rv, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
event->SetTrusted(true);
event->mOldVersion = aOldVersion;
event->mNewVersion = aNewVersion;
return event.forget();
}
// static
already_AddRefed<nsIRunnable>
IDBVersionChangeEvent::CreateRunnableInternal(mozilla::dom::EventTarget* aTarget,
const nsAString& aType,
uint64_t aOldVersion,
uint64_t aNewVersion)
already_AddRefed<IDBVersionChangeEvent>
IDBVersionChangeEvent::Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const IDBVersionChangeEventInit& aOptions,
ErrorResult& aRv)
{
nsRefPtr<Event> event =
CreateInternal(aTarget, aType, aOldVersion, aNewVersion);
NS_ENSURE_TRUE(event, nullptr);
nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports());
nsCOMPtr<nsIRunnable> runnable(new EventFiringRunnable(aTarget, event));
return runnable.forget();
return CreateInternal(target,
aType,
aOptions.mOldVersion,
aOptions.mNewVersion);
}
NS_IMPL_ADDREF_INHERITED(IDBVersionChangeEvent, Event)
@ -96,3 +94,13 @@ NS_IMPL_RELEASE_INHERITED(IDBVersionChangeEvent, Event)
NS_INTERFACE_MAP_BEGIN(IDBVersionChangeEvent)
NS_INTERFACE_MAP_ENTRY(IDBVersionChangeEvent)
NS_INTERFACE_MAP_END_INHERITING(Event)
JSObject*
IDBVersionChangeEvent::WrapObject(JSContext* aCx)
{
return IDBVersionChangeEventBinding::Wrap(aCx, this);
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -7,28 +7,28 @@
#ifndef mozilla_dom_indexeddb_idbevents_h__
#define mozilla_dom_indexeddb_idbevents_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "nsIRunnable.h"
#include "js/RootingAPI.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/IDBVersionChangeEventBinding.h"
#define SUCCESS_EVT_STR "success"
#define ERROR_EVT_STR "error"
#define COMPLETE_EVT_STR "complete"
#define ABORT_EVT_STR "abort"
#define VERSIONCHANGE_EVT_STR "versionchange"
#define BLOCKED_EVT_STR "blocked"
#define UPGRADENEEDED_EVT_STR "upgradeneeded"
#define IDBVERSIONCHANGEEVENT_IID \
{ 0x3b65d4c3, 0x73ad, 0x492e, \
{ 0xb1, 0x2d, 0x15, 0xf9, 0xda, 0xc2, 0x08, 0x4b } }
{0x3b65d4c3, 0x73ad, 0x492e, {0xb1, 0x2d, 0x15, 0xf9, 0xda, 0xc2, 0x08, 0x4b}}
BEGIN_INDEXEDDB_NAMESPACE
class nsAString;
class nsDependentString;
namespace mozilla {
class ErrorResult;
namespace dom {
class EventTarget;
class GlobalObject;
struct IDBVersionChangeEventInit;
namespace indexedDB {
enum Bubbles {
eDoesNotBubble,
@ -40,125 +40,94 @@ enum Cancelable {
eCancelable
};
extern const char16_t* kAbortEventType;
extern const char16_t* kBlockedEventType;
extern const char16_t* kCompleteEventType;
extern const char16_t* kErrorEventType;
extern const char16_t* kSuccessEventType;
extern const char16_t* kUpgradeNeededEventType;
extern const char16_t* kVersionChangeEventType;
already_AddRefed<nsIDOMEvent>
CreateGenericEvent(mozilla::dom::EventTarget* aOwner,
const nsAString& aType,
CreateGenericEvent(EventTarget* aOwner,
const nsDependentString& aType,
Bubbles aBubbles,
Cancelable aCancelable);
class IDBVersionChangeEvent : public Event
class IDBVersionChangeEvent MOZ_FINAL : public Event
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_TO_EVENT
NS_DECLARE_STATIC_IID_ACCESSOR(IDBVERSIONCHANGEEVENT_IID)
uint64_t mOldVersion;
Nullable<uint64_t> mNewVersion;
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE
public:
static already_AddRefed<IDBVersionChangeEvent>
Create(EventTarget* aOwner,
const nsDependentString& aName,
uint64_t aOldVersion,
uint64_t aNewVersion)
{
return mozilla::dom::IDBVersionChangeEventBinding::Wrap(aCx, this);
Nullable<uint64_t> newVersion(aNewVersion);
return CreateInternal(aOwner, aName, aOldVersion, newVersion);
}
static already_AddRefed<IDBVersionChangeEvent>
Create(EventTarget* aOwner,
const nsDependentString& aName,
uint64_t aOldVersion)
{
Nullable<uint64_t> newVersion(0);
newVersion.SetNull();
return CreateInternal(aOwner, aName, aOldVersion, newVersion);
}
static already_AddRefed<IDBVersionChangeEvent>
Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const IDBVersionChangeEventInit& aOptions,
ErrorResult& aRv)
{
uint64_t newVersion = 0;
if (!aOptions.mNewVersion.IsNull()) {
newVersion = aOptions.mNewVersion.Value();
}
nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports());
return CreateInternal(target, aType, aOptions.mOldVersion, newVersion);
}
ErrorResult& aRv);
uint64_t OldVersion()
uint64_t
OldVersion() const
{
return mOldVersion;
}
mozilla::dom::Nullable<uint64_t> GetNewVersion()
Nullable<uint64_t>
GetNewVersion() const
{
return mNewVersion
? mozilla::dom::Nullable<uint64_t>(mNewVersion)
: mozilla::dom::Nullable<uint64_t>();
return mNewVersion;
}
inline static already_AddRefed<Event>
Create(mozilla::dom::EventTarget* aOwner,
int64_t aOldVersion,
int64_t aNewVersion)
{
return CreateInternal(aOwner,
NS_LITERAL_STRING(VERSIONCHANGE_EVT_STR),
aOldVersion, aNewVersion);
}
NS_DECLARE_STATIC_IID_ACCESSOR(IDBVERSIONCHANGEEVENT_IID)
inline static already_AddRefed<Event>
CreateBlocked(mozilla::dom::EventTarget* aOwner,
uint64_t aOldVersion,
uint64_t aNewVersion)
{
return CreateInternal(aOwner, NS_LITERAL_STRING(BLOCKED_EVT_STR),
aOldVersion, aNewVersion);
}
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_TO_EVENT
inline static already_AddRefed<Event>
CreateUpgradeNeeded(mozilla::dom::EventTarget* aOwner,
uint64_t aOldVersion,
uint64_t aNewVersion)
{
return CreateInternal(aOwner,
NS_LITERAL_STRING(UPGRADENEEDED_EVT_STR),
aOldVersion, aNewVersion);
}
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
inline static already_AddRefed<nsIRunnable>
CreateRunnable(mozilla::dom::EventTarget* aTarget,
uint64_t aOldVersion,
uint64_t aNewVersion)
{
return CreateRunnableInternal(aTarget,
NS_LITERAL_STRING(VERSIONCHANGE_EVT_STR),
aOldVersion, aNewVersion);
}
static already_AddRefed<nsIRunnable>
CreateBlockedRunnable(mozilla::dom::EventTarget* aTarget,
uint64_t aOldVersion,
uint64_t aNewVersion)
{
return CreateRunnableInternal(aTarget,
NS_LITERAL_STRING(BLOCKED_EVT_STR),
aOldVersion, aNewVersion);
}
protected:
explicit IDBVersionChangeEvent(mozilla::dom::EventTarget* aOwner)
private:
IDBVersionChangeEvent(EventTarget* aOwner, uint64_t aOldVersion)
: Event(aOwner, nullptr, nullptr)
, mOldVersion(aOldVersion)
{
SetIsDOMBinding();
}
virtual ~IDBVersionChangeEvent() { }
~IDBVersionChangeEvent()
{ }
static already_AddRefed<IDBVersionChangeEvent>
CreateInternal(mozilla::dom::EventTarget* aOwner,
const nsAString& aType,
CreateInternal(EventTarget* aOwner,
const nsAString& aName,
uint64_t aOldVersion,
uint64_t aNewVersion);
static already_AddRefed<nsIRunnable>
CreateRunnableInternal(mozilla::dom::EventTarget* aOwner,
const nsAString& aType,
uint64_t aOldVersion,
uint64_t aNewVersion);
uint64_t mOldVersion;
uint64_t mNewVersion;
Nullable<uint64_t> aNewVersion);
};
NS_DEFINE_STATIC_IID_ACCESSOR(IDBVersionChangeEvent, IDBVERSIONCHANGEEVENT_IID)
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbevents_h__

File diff suppressed because it is too large Load Diff

View File

@ -7,219 +7,203 @@
#ifndef mozilla_dom_indexeddb_idbfactory_h__
#define mozilla_dom_indexeddb_idbfactory_h__
#include "mozilla/dom/BindingDeclarations.h" // for Optional
#include "mozilla/Attributes.h"
#include "mozilla/dom/StorageTypeBinding.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/StoragePrivilege.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISupports.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsWrapperCache.h"
class mozIStorageConnection;
class nsIFile;
class nsIFileURL;
class nsIPrincipal;
class nsPIDOMWindow;
template<typename> class nsRefPtr;
struct PRThread;
namespace mozilla {
class ErrorResult;
namespace ipc {
class PBackgroundChild;
class PrincipalInfo;
} // namespace ipc
namespace dom {
class nsIContentParent;
struct IDBOpenDBOptions;
class TabChild;
namespace indexedDB {
struct DatabaseInfo;
class IDBDatabase;
class BackgroundFactoryChild;
class FactoryRequestParams;
class IDBOpenDBRequest;
class IndexedDBChild;
class IndexedDBParent;
struct ObjectStoreInfo;
class IDBFactory MOZ_FINAL : public nsISupports,
public nsWrapperCache
class IDBFactory MOZ_FINAL
: public nsISupports
, public nsWrapperCache
{
typedef mozilla::dom::nsIContentParent nsIContentParent;
typedef mozilla::dom::quota::PersistenceType PersistenceType;
typedef nsTArray<nsRefPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
typedef mozilla::dom::StorageType StorageType;
typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
class BackgroundCreateCallback;
struct PendingRequestInfo;
// Called when using IndexedDB from a window in a different process.
static nsresult Create(nsPIDOMWindow* aWindow,
const nsACString& aGroup,
const nsACString& aASCIIOrigin,
nsIContentParent* aContentParent,
IDBFactory** aFactory);
// Called when using IndexedDB from a window in the current process.
static nsresult Create(nsPIDOMWindow* aWindow,
nsIContentParent* aContentParent,
IDBFactory** aFactory)
{
return Create(aWindow, EmptyCString(), EmptyCString(), aContentParent,
aFactory);
}
// Called when using IndexedDB from a JS component or a JSM in the current
// process.
static nsresult Create(JSContext* aCx,
JS::Handle<JSObject*> aOwningObject,
nsIContentParent* aContentParent,
IDBFactory** aFactory);
// Called when using IndexedDB from a JS component or a JSM in a different
// process or from a C++ component.
static nsresult Create(nsIContentParent* aContentParent,
IDBFactory** aFactory);
static already_AddRefed<nsIFileURL>
GetDatabaseFileURL(nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin);
static already_AddRefed<mozIStorageConnection>
GetConnection(const nsAString& aDatabaseFilePath,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin);
static nsresult
SetDefaultPragmas(mozIStorageConnection* aConnection);
static nsresult
LoadDatabaseInformation(mozIStorageConnection* aConnection,
const nsACString& aDatabaseId,
uint64_t* aVersion,
ObjectStoreInfoArray& aObjectStores);
static nsresult
SetDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
uint64_t aVersion,
ObjectStoreInfoArray& aObjectStores);
nsresult
OpenInternal(const nsAString& aName,
int64_t aVersion,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aASCIIOrigin,
StoragePrivilege aStoragePrivilege,
bool aDeleting,
IDBOpenDBRequest** _retval);
nsresult
OpenInternal(const nsAString& aName,
int64_t aVersion,
PersistenceType aPersistenceType,
bool aDeleting,
IDBOpenDBRequest** _retval)
{
return OpenInternal(aName, aVersion, aPersistenceType, mGroup, mASCIIOrigin,
mPrivilege, aDeleting, _retval);
}
void
SetActor(IndexedDBChild* aActorChild)
{
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
mActorChild = aActorChild;
}
void
SetActor(IndexedDBParent* aActorParent)
{
NS_ASSERTION(!aActorParent || !mActorParent, "Shouldn't have more than one!");
mActorParent = aActorParent;
}
const nsCString&
GetASCIIOrigin() const
{
return mASCIIOrigin;
}
bool
FromIPC()
{
return !!mContentParent;
}
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
nsPIDOMWindow*
GetParentObject() const
{
return mWindow;
}
already_AddRefed<IDBOpenDBRequest>
Open(const nsAString& aName, uint64_t aVersion, ErrorResult& aRv)
{
return Open(nullptr, aName, Optional<uint64_t>(aVersion),
Optional<mozilla::dom::StorageType>(), false, aRv);
}
already_AddRefed<IDBOpenDBRequest>
Open(const nsAString& aName, const IDBOpenDBOptions& aOptions,
ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
DeleteDatabase(const nsAString& aName, const IDBOpenDBOptions& aOptions,
ErrorResult& aRv);
int16_t
Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
JS::Handle<JS::Value> aSecond, ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
uint64_t aVersion, ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
const IDBOpenDBOptions& aOptions, ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
DeleteForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
const IDBOpenDBOptions& aOptions, ErrorResult& aRv);
private:
IDBFactory();
~IDBFactory();
already_AddRefed<IDBOpenDBRequest>
Open(nsIPrincipal* aPrincipal, const nsAString& aName,
const Optional<uint64_t>& aVersion,
const Optional<mozilla::dom::StorageType>& aStorageType, bool aDelete,
ErrorResult& aRv);
nsCString mGroup;
nsCString mASCIIOrigin;
StoragePrivilege mPrivilege;
PersistenceType mDefaultPersistenceType;
nsAutoPtr<PrincipalInfo> mPrincipalInfo;
// If this factory lives on a window then mWindow must be non-null. Otherwise
// mOwningObject must be non-null.
nsCOMPtr<nsPIDOMWindow> mWindow;
JS::Heap<JSObject*> mOwningObject;
IndexedDBChild* mActorChild;
IndexedDBParent* mActorParent;
// This will only be set if the factory belongs to a window in a child
// process.
nsRefPtr<TabChild> mTabChild;
mozilla::dom::nsIContentParent* mContentParent;
nsTArray<nsAutoPtr<PendingRequestInfo>> mPendingRequests;
BackgroundFactoryChild* mBackgroundActor;
#ifdef DEBUG
PRThread* mOwningThread;
#endif
bool mRootedOwningObject;
bool mBackgroundActorFailed;
bool mPrivateBrowsingMode;
public:
static nsresult
CreateForWindow(nsPIDOMWindow* aWindow,
IDBFactory** aFactory);
static nsresult
CreateForChromeJS(JSContext* aCx,
JS::Handle<JSObject*> aOwningObject,
IDBFactory** aFactory);
static nsresult
CreateForDatastore(JSContext* aCx,
JS::Handle<JSObject*> aOwningObject,
IDBFactory** aFactory);
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
void
SetBackgroundActor(BackgroundFactoryChild* aBackgroundActor);
void
ClearBackgroundActor()
{
AssertIsOnOwningThread();
mBackgroundActor = nullptr;
}
nsPIDOMWindow*
GetParentObject() const
{
return mWindow;
}
TabChild*
GetTabChild() const
{
return mTabChild;
}
PrincipalInfo*
GetPrincipalInfo() const
{
AssertIsOnOwningThread();
return mPrincipalInfo;
}
already_AddRefed<IDBOpenDBRequest>
Open(const nsAString& aName,
uint64_t aVersion,
ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
Open(const nsAString& aName,
const IDBOpenDBOptions& aOptions,
ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
DeleteDatabase(const nsAString& aName,
const IDBOpenDBOptions& aOptions,
ErrorResult& aRv);
int16_t
Cmp(JSContext* aCx,
JS::Handle<JS::Value> aFirst,
JS::Handle<JS::Value> aSecond,
ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
OpenForPrincipal(nsIPrincipal* aPrincipal,
const nsAString& aName,
uint64_t aVersion,
ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
OpenForPrincipal(nsIPrincipal* aPrincipal,
const nsAString& aName,
const IDBOpenDBOptions& aOptions,
ErrorResult& aRv);
already_AddRefed<IDBOpenDBRequest>
DeleteForPrincipal(nsIPrincipal* aPrincipal,
const nsAString& aName,
const IDBOpenDBOptions& aOptions,
ErrorResult& aRv);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
private:
IDBFactory();
~IDBFactory();
static nsresult
CreateForJSInternal(JSContext* aCx,
JS::Handle<JSObject*> aOwningObject,
nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
IDBFactory** aFactory);
already_AddRefed<IDBOpenDBRequest>
OpenInternal(nsIPrincipal* aPrincipal,
const nsAString& aName,
const Optional<uint64_t>& aVersion,
const Optional<StorageType>& aStorageType,
bool aDeleting,
ErrorResult& aRv);
nsresult
BackgroundActorCreated(PBackgroundChild* aBackgroundActor);
void
BackgroundActorFailed();
nsresult
InitiateRequest(IDBOpenDBRequest* aRequest,
const FactoryRequestParams& aParams);
};
} // namespace indexedDB

View File

@ -16,16 +16,16 @@
#include "nsServiceManagerUtils.h"
#include "nsWidgetsCID.h"
namespace mozilla {
namespace dom {
namespace indexedDB {
namespace {
NS_DEFINE_CID(kAppShellCID2, NS_APPSHELL_CID);
} // anonymous namespace
namespace mozilla {
namespace dom {
namespace indexedDB {
IDBFileHandle::IDBFileHandle(FileMode aMode,
RequestMode aRequestMode,
IDBMutableFile* aMutableFile)
@ -158,10 +158,10 @@ IDBFileHandle::OnCompleteOrAbort(bool aAborted)
{
nsCOMPtr<nsIDOMEvent> event;
if (aAborted) {
event = CreateGenericEvent(this, NS_LITERAL_STRING(ABORT_EVT_STR),
event = CreateGenericEvent(this, nsDependentString(kAbortEventType),
eDoesBubble, eNotCancelable);
} else {
event = CreateGenericEvent(this, NS_LITERAL_STRING(COMPLETE_EVT_STR),
event = CreateGenericEvent(this, nsDependentString(kCompleteEventType),
eDoesNotBubble, eNotCancelable);
}
if (NS_WARN_IF(!event)) {

File diff suppressed because it is too large Load Diff

View File

@ -7,245 +7,207 @@
#ifndef mozilla_dom_indexeddb_idbindex_h__
#define mozilla_dom_indexeddb_idbindex_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "js/RootingAPI.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/IDBCursorBinding.h"
#include "mozilla/ErrorResult.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISupports.h"
#include "nsTArrayForwardDeclare.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "mozilla/dom/indexedDB/KeyPath.h"
class nsIScriptContext;
class nsPIDOMWindow;
BEGIN_INDEXEDDB_NAMESPACE
namespace mozilla {
class ErrorResult;
namespace dom {
template <typename> class Sequence;
namespace indexedDB {
class AsyncConnectionHelper;
class IDBCursor;
class IDBKeyRange;
class IDBObjectStore;
class IDBRequest;
class IndexedDBIndexChild;
class IndexedDBIndexParent;
class IndexMetadata;
class Key;
class KeyPath;
struct IndexInfo;
class IDBIndex MOZ_FINAL : public nsISupports,
public nsWrapperCache
class IDBIndex MOZ_FINAL
: public nsISupports
, public nsWrapperCache
{
nsRefPtr<IDBObjectStore> mObjectStore;
JS::Heap<JS::Value> mCachedKeyPath;
// This normally points to the IndexMetadata owned by the parent IDBDatabase
// object. However, if this index is part of a versionchange transaction and
// it gets deleted then the metadata is copied into mDeletedMetadata and
// mMetadata is set to point at mDeletedMetadata.
const IndexMetadata* mMetadata;
nsAutoPtr<IndexMetadata> mDeletedMetadata;
const int64_t mId;
bool mRooted;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBIndex)
static already_AddRefed<IDBIndex>
Create(IDBObjectStore* aObjectStore,
const IndexInfo* aIndexInfo,
bool aCreating);
Create(IDBObjectStore* aObjectStore, const IndexMetadata& aMetadata);
IDBObjectStore* ObjectStore()
int64_t
Id() const
{
return mObjectStore;
}
AssertIsOnOwningThread();
const int64_t Id() const
{
return mId;
}
const nsString& Name() const
{
return mName;
}
const nsString&
Name() const;
bool IsUnique() const
{
return mUnique;
}
bool
Unique() const;
bool IsMultiEntry() const
{
return mMultiEntry;
}
bool
MultiEntry() const;
const KeyPath& GetKeyPath() const
{
return mKeyPath;
}
void
SetActor(IndexedDBIndexChild* aActorChild)
{
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
mActorChild = aActorChild;
}
void
SetActor(IndexedDBIndexParent* aActorParent)
{
NS_ASSERTION(!aActorParent || !mActorParent,
"Shouldn't have more than one!");
mActorParent = aActorParent;
}
IndexedDBIndexChild*
GetActorChild() const
{
return mActorChild;
}
IndexedDBIndexParent*
GetActorParent() const
{
return mActorParent;
}
already_AddRefed<IDBRequest>
GetInternal(IDBKeyRange* aKeyRange,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
GetKeyInternal(IDBKeyRange* aKeyRange,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
GetAllInternal(IDBKeyRange* aKeyRange,
uint32_t aLimit,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
GetAllKeysInternal(IDBKeyRange* aKeyRange,
uint32_t aLimit,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
CountInternal(IDBKeyRange* aKeyRange,
ErrorResult& aRv);
nsresult OpenCursorFromChildProcess(
IDBRequest* aRequest,
size_t aDirection,
const Key& aKey,
const Key& aObjectKey,
IDBCursor** _retval);
already_AddRefed<IDBRequest>
OpenKeyCursorInternal(IDBKeyRange* aKeyRange,
size_t aDirection,
ErrorResult& aRv);
nsresult OpenCursorInternal(IDBKeyRange* aKeyRange,
size_t aDirection,
IDBRequest** _retval);
nsresult OpenCursorFromChildProcess(
IDBRequest* aRequest,
size_t aDirection,
const Key& aKey,
const Key& aObjectKey,
const SerializedStructuredCloneReadInfo& aCloneInfo,
nsTArray<StructuredCloneFile>& aBlobs,
IDBCursor** _retval);
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
IDBObjectStore*
GetParentObject() const
{
return mObjectStore;
}
void
GetName(nsString& aName) const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
aName.Assign(mName);
}
const KeyPath&
GetKeyPath() const;
IDBObjectStore*
ObjectStore() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
return mObjectStore;
}
nsPIDOMWindow*
GetParentObject() const;
void
GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
GetName(nsString& aName) const
{
aName = Name();
}
void
GetKeyPath(JSContext* aCx,
JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv);
bool
MultiEntry() const
already_AddRefed<IDBRequest>
OpenCursor(JSContext* aCx,
JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection,
ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return mMultiEntry;
}
AssertIsOnOwningThread();
bool
Unique() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return mUnique;
return OpenCursorInternal(/* aKeysOnly */ false, aCx, aRange, aDirection,
aRv);
}
already_AddRefed<IDBRequest>
OpenCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection, ErrorResult& aRv);
OpenKeyCursor(JSContext* aCx,
JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
return OpenCursorInternal(/* aKeysOnly */ true, aCx, aRange, aDirection,
aRv);
}
already_AddRefed<IDBRequest>
OpenKeyCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection, ErrorResult& aRv);
Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
{
AssertIsOnOwningThread();
return GetInternal(/* aKeyOnly */ false, aCx, aKey, aRv);
}
already_AddRefed<IDBRequest>
Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
{
AssertIsOnOwningThread();
already_AddRefed<IDBRequest>
GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
return GetInternal(/* aKeyOnly */ true, aCx, aKey, aRv);
}
already_AddRefed<IDBRequest>
Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
ErrorResult& aRv);
void
GetStoreName(nsString& aStoreName) const
already_AddRefed<IDBRequest>
GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit, ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mObjectStore->GetName(aStoreName);
AssertIsOnOwningThread();
return GetAllInternal(/* aKeysOnly */ false, aCx, aKey, aLimit, aRv);
}
already_AddRefed<IDBRequest>
GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit, ErrorResult& aRv);
already_AddRefed<IDBRequest>
GetAllKeys(JSContext* aCx, JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit, ErrorResult& aRv);
const Optional<uint32_t>& aLimit, ErrorResult& aRv)
{
AssertIsOnOwningThread();
return GetAllInternal(/* aKeysOnly */ true, aCx, aKey, aLimit, aRv);
}
void
RefreshMetadata(bool aMayDelete);
void
NoteDeletion();
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
private:
IDBIndex();
IDBIndex(IDBObjectStore* aObjectStore, const IndexMetadata* aMetadata);
~IDBIndex();
nsRefPtr<IDBObjectStore> mObjectStore;
already_AddRefed<IDBRequest>
GetInternal(bool aKeyOnly,
JSContext* aCx,
JS::Handle<JS::Value> aKey,
ErrorResult& aRv);
int64_t mId;
nsString mName;
KeyPath mKeyPath;
JS::Heap<JS::Value> mCachedKeyPath;
already_AddRefed<IDBRequest>
GetAllInternal(bool aKeysOnly,
JSContext* aCx,
JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit,
ErrorResult& aRv);
IndexedDBIndexChild* mActorChild;
IndexedDBIndexParent* mActorParent;
bool mUnique;
bool mMultiEntry;
bool mRooted;
already_AddRefed<IDBRequest>
OpenCursorInternal(bool aKeysOnly,
JSContext* aCx,
JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection,
ErrorResult& aRv);
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbindex_h__

View File

@ -4,30 +4,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "IDBKeyRange.h"
#include "nsIXPConnect.h"
#include "nsJSUtils.h"
#include "nsThreadUtils.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "Key.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/IDBKeyRangeBinding.h"
#include "mozilla/dom/indexedDB/PIndexedDBIndex.h"
#include "mozilla/dom/indexedDB/PIndexedDBObjectStore.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
using namespace mozilla;
using namespace mozilla::dom;
USING_INDEXEDDB_NAMESPACE
using namespace mozilla::dom::indexedDB::ipc;
namespace mozilla {
namespace dom {
namespace indexedDB {
namespace {
inline nsresult
nsresult
GetKeyFromJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
Key& aKey,
@ -35,8 +26,7 @@ GetKeyFromJSVal(JSContext* aCx,
{
nsresult rv = aKey.SetFromJSVal(aCx, aVal);
if (NS_FAILED(rv)) {
NS_ASSERTION(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB,
"Bad error code!");
MOZ_ASSERT(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
return rv;
}
@ -49,6 +39,42 @@ GetKeyFromJSVal(JSContext* aCx,
} // anonymous namespace
IDBKeyRange::IDBKeyRange(nsISupports* aGlobal,
bool aLowerOpen,
bool aUpperOpen,
bool aIsOnly)
: mGlobal(aGlobal)
, mCachedLowerVal(JSVAL_VOID)
, mCachedUpperVal(JSVAL_VOID)
, mLowerOpen(aLowerOpen)
, mUpperOpen(aUpperOpen)
, mIsOnly(aIsOnly)
, mHaveCachedLowerVal(false)
, mHaveCachedUpperVal(false)
, mRooted(false)
{
#ifdef DEBUG
mOwningThread = PR_GetCurrentThread();
#endif
AssertIsOnOwningThread();
}
IDBKeyRange::~IDBKeyRange()
{
DropJSObjects();
}
#ifdef DEBUG
void
IDBKeyRange::AssertIsOnOwningThread() const
{
MOZ_ASSERT(mOwningThread);
MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
}
#endif // DEBUG
// static
nsresult
IDBKeyRange::FromJSVal(JSContext* aCx,
@ -87,9 +113,8 @@ IDBKeyRange::FromJSVal(JSContext* aCx,
}
// static
template <class T>
already_AddRefed<IDBKeyRange>
IDBKeyRange::FromSerializedKeyRange(const T& aKeyRange)
IDBKeyRange::FromSerialized(const SerializedKeyRange& aKeyRange)
{
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(nullptr, aKeyRange.lowerOpen(), aKeyRange.upperOpen(),
@ -101,12 +126,11 @@ IDBKeyRange::FromSerializedKeyRange(const T& aKeyRange)
return keyRange.forget();
}
template <class T>
void
IDBKeyRange::ToSerializedKeyRange(T& aKeyRange)
IDBKeyRange::ToSerialized(SerializedKeyRange& aKeyRange) const
{
aKeyRange.lowerOpen() = IsLowerOpen();
aKeyRange.upperOpen() = IsUpperOpen();
aKeyRange.lowerOpen() = LowerOpen();
aKeyRange.upperOpen() = UpperOpen();
aKeyRange.isOnly() = IsOnly();
aKeyRange.lower() = Lower();
@ -115,6 +139,76 @@ IDBKeyRange::ToSerializedKeyRange(T& aKeyRange)
}
}
void
IDBKeyRange::GetBindingClause(const nsACString& aKeyColumnName,
nsACString& _retval) const
{
NS_NAMED_LITERAL_CSTRING(andStr, " AND ");
NS_NAMED_LITERAL_CSTRING(spacecolon, " :");
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
if (IsOnly()) {
// Both keys are set and they're equal.
_retval = andStr + aKeyColumnName + NS_LITERAL_CSTRING(" =") +
spacecolon + lowerKey;
return;
}
nsAutoCString clause;
if (!Lower().IsUnset()) {
// Lower key is set.
clause.Append(andStr + aKeyColumnName);
clause.AppendLiteral(" >");
if (!LowerOpen()) {
clause.Append('=');
}
clause.Append(spacecolon + lowerKey);
}
if (!Upper().IsUnset()) {
// Upper key is set.
clause.Append(andStr + aKeyColumnName);
clause.AppendLiteral(" <");
if (!UpperOpen()) {
clause.Append('=');
}
clause.Append(spacecolon + NS_LITERAL_CSTRING("upper_key"));
}
_retval = clause;
}
nsresult
IDBKeyRange::BindToStatement(mozIStorageStatement* aStatement) const
{
MOZ_ASSERT(aStatement);
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
if (IsOnly()) {
return Lower().BindToStatement(aStatement, lowerKey);
}
nsresult rv;
if (!Lower().IsUnset()) {
rv = Lower().BindToStatement(aStatement, lowerKey);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (!Upper().IsUnset()) {
rv = Upper().BindToStatement(aStatement, NS_LITERAL_CSTRING("upper_key"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange)
@ -145,19 +239,14 @@ IDBKeyRange::DropJSObjects()
if (!mRooted) {
return;
}
mCachedLowerVal = JS::UndefinedValue();
mCachedUpperVal = JS::UndefinedValue();
mCachedLowerVal.setUndefined();
mCachedUpperVal.setUndefined();
mHaveCachedLowerVal = false;
mHaveCachedUpperVal = false;
mRooted = false;
mozilla::DropJSObjects(this);
}
IDBKeyRange::~IDBKeyRange()
{
DropJSObjects();
}
JSObject*
IDBKeyRange::WrapObject(JSContext* aCx)
{
@ -168,7 +257,7 @@ void
IDBKeyRange::GetLower(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
if (!mHaveCachedLowerVal) {
if (!mRooted) {
@ -192,7 +281,7 @@ void
IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
if (!mHaveCachedUpperVal) {
if (!mRooted) {
@ -215,10 +304,9 @@ IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::Only(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
JS::Handle<JS::Value> aValue,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(aGlobal.GetAsSupports(), false, false, true);
@ -233,11 +321,10 @@ IDBKeyRange::Only(const GlobalObject& aGlobal,
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::LowerBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, bool aOpen,
JS::Handle<JS::Value> aValue,
bool aOpen,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(aGlobal.GetAsSupports(), aOpen, true, false);
@ -252,11 +339,10 @@ IDBKeyRange::LowerBound(const GlobalObject& aGlobal,
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::UpperBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, bool aOpen,
JS::Handle<JS::Value> aValue,
bool aOpen,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(aGlobal.GetAsSupports(), true, aOpen, false);
@ -271,11 +357,12 @@ IDBKeyRange::UpperBound(const GlobalObject& aGlobal,
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::Bound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv)
JS::Handle<JS::Value> aLower,
JS::Handle<JS::Value> aUpper,
bool aLowerOpen,
bool aUpperOpen,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(aGlobal.GetAsSupports(), aLowerOpen, aUpperOpen, false);
@ -298,9 +385,6 @@ IDBKeyRange::Bound(const GlobalObject& aGlobal,
return keyRange.forget();
}
// Explicitly instantiate for all our key range types... Grumble.
template already_AddRefed<IDBKeyRange>
IDBKeyRange::FromSerializedKeyRange<KeyRange> (const KeyRange& aKeyRange);
template void
IDBKeyRange::ToSerializedKeyRange<KeyRange> (KeyRange& aKeyRange);
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -7,144 +7,137 @@
#ifndef mozilla_dom_indexeddb_idbkeyrange_h__
#define mozilla_dom_indexeddb_idbkeyrange_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "js/RootingAPI.h"
#include "js/Value.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/indexedDB/Key.h"
#include "nsISupports.h"
#include "mozilla/ErrorResult.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISupports.h"
#include "nsString.h"
class mozIStorageStatement;
struct PRThread;
namespace mozilla {
class ErrorResult;
namespace dom {
class GlobalObject;
} // namespace dom
} // namespace mozilla
BEGIN_INDEXEDDB_NAMESPACE
namespace indexedDB {
namespace ipc {
class KeyRange;
} // namespace ipc
class SerializedKeyRange;
class IDBKeyRange MOZ_FINAL : public nsISupports
class IDBKeyRange MOZ_FINAL
: public nsISupports
{
nsCOMPtr<nsISupports> mGlobal;
Key mLower;
Key mUpper;
JS::Heap<JS::Value> mCachedLowerVal;
JS::Heap<JS::Value> mCachedUpperVal;
const bool mLowerOpen : 1;
const bool mUpperOpen : 1;
const bool mIsOnly : 1;
bool mHaveCachedLowerVal : 1;
bool mHaveCachedUpperVal : 1;
bool mRooted : 1;
#ifdef DEBUG
PRThread* mOwningThread;
#endif
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBKeyRange)
static nsresult FromJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
IDBKeyRange** aKeyRange);
static nsresult
FromJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
IDBKeyRange** aKeyRange);
template <class T>
static already_AddRefed<IDBKeyRange>
FromSerializedKeyRange(const T& aKeyRange);
FromSerialized(const SerializedKeyRange& aKeyRange);
const Key& Lower() const
static already_AddRefed<IDBKeyRange>
Only(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue,
ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
LowerBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue,
bool aOpen,
ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
UpperBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue,
bool aOpen,
ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
Bound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aLower,
JS::Handle<JS::Value> aUpper,
bool aLowerOpen,
bool aUpperOpen,
ErrorResult& aRv);
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
void
ToSerialized(SerializedKeyRange& aKeyRange) const;
const Key&
Lower() const
{
return mLower;
}
Key& Lower()
Key&
Lower()
{
return mLower;
}
const Key& Upper() const
const Key&
Upper() const
{
return mIsOnly ? mLower : mUpper;
}
Key& Upper()
Key&
Upper()
{
return mIsOnly ? mLower : mUpper;
}
// TODO: Remove these in favour of LowerOpen() / UpperOpen(), bug 900578.
bool IsLowerOpen() const
{
return mLowerOpen;
}
bool IsUpperOpen() const
{
return mUpperOpen;
}
bool IsOnly() const
bool
IsOnly() const
{
return mIsOnly;
}
void GetBindingClause(const nsACString& aKeyColumnName,
nsACString& _retval) const
{
NS_NAMED_LITERAL_CSTRING(andStr, " AND ");
NS_NAMED_LITERAL_CSTRING(spacecolon, " :");
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
void
GetBindingClause(const nsACString& aKeyColumnName,
nsACString& _retval) const;
if (IsOnly()) {
// Both keys are set and they're equal.
_retval = andStr + aKeyColumnName + NS_LITERAL_CSTRING(" =") +
spacecolon + lowerKey;
}
else {
nsAutoCString clause;
nsresult
BindToStatement(mozIStorageStatement* aStatement) const;
if (!Lower().IsUnset()) {
// Lower key is set.
clause.Append(andStr + aKeyColumnName);
clause.AppendLiteral(" >");
if (!IsLowerOpen()) {
clause.Append('=');
}
clause.Append(spacecolon + lowerKey);
}
if (!Upper().IsUnset()) {
// Upper key is set.
clause.Append(andStr + aKeyColumnName);
clause.AppendLiteral(" <");
if (!IsUpperOpen()) {
clause.Append('=');
}
clause.Append(spacecolon + NS_LITERAL_CSTRING("upper_key"));
}
_retval = clause;
}
}
nsresult BindToStatement(mozIStorageStatement* aStatement) const
{
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
if (IsOnly()) {
return Lower().BindToStatement(aStatement, lowerKey);
}
nsresult rv;
if (!Lower().IsUnset()) {
rv = Lower().BindToStatement(aStatement, lowerKey);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
if (!Upper().IsUnset()) {
rv = Upper().BindToStatement(aStatement, NS_LITERAL_CSTRING("upper_key"));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
return NS_OK;
}
template <class T>
void ToSerializedKeyRange(T& aKeyRange);
void DropJSObjects();
void
DropJSObjects();
// WebIDL
JSObject*
@ -176,48 +169,17 @@ public:
return mUpperOpen;
}
static already_AddRefed<IDBKeyRange>
Only(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
LowerBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, bool aOpen, ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
UpperBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, bool aOpen, ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
Bound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv);
private:
IDBKeyRange(nsISupports* aGlobal,
bool aLowerOpen,
bool aUpperOpen,
bool aIsOnly)
: mGlobal(aGlobal), mCachedLowerVal(JSVAL_VOID), mCachedUpperVal(JSVAL_VOID),
mLowerOpen(aLowerOpen), mUpperOpen(aUpperOpen), mIsOnly(aIsOnly),
mHaveCachedLowerVal(false), mHaveCachedUpperVal(false), mRooted(false)
{ }
bool aIsOnly);
~IDBKeyRange();
nsCOMPtr<nsISupports> mGlobal;
Key mLower;
Key mUpper;
JS::Heap<JS::Value> mCachedLowerVal;
JS::Heap<JS::Value> mCachedUpperVal;
const bool mLowerOpen;
const bool mUpperOpen;
const bool mIsOnly;
bool mHaveCachedLowerVal;
bool mHaveCachedUpperVal;
bool mRooted;
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbkeyrange_h__

View File

@ -6,26 +6,36 @@
#include "IDBMutableFile.h"
#include "nsIDOMFile.h"
#include "FileSnapshot.h"
#include "FileInfo.h"
#include "IDBDatabase.h"
#include "IDBFactory.h"
#include "IDBFileHandle.h"
#include "IDBFileRequest.h"
#include "IndexedDatabaseManager.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/FileService.h"
#include "mozilla/dom/IDBMutableFileBinding.h"
#include "mozilla/dom/MetadataHelper.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
#include "mozilla/dom/quota/FileStreams.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsContentUtils.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsIDOMFile.h"
#include "nsIPrincipal.h"
#include "FileSnapshot.h"
#include "IDBDatabase.h"
#include "IDBFileHandle.h"
#include "IDBFileRequest.h"
namespace mozilla {
namespace dom {
namespace indexedDB {
using namespace mozilla::dom;
USING_INDEXEDDB_NAMESPACE
USING_QUOTA_NAMESPACE
using namespace mozilla::dom::quota;
using namespace mozilla::ipc;
namespace {
@ -48,7 +58,6 @@ public:
ReleaseObjects() MOZ_OVERRIDE
{
mMutableFile = nullptr;
MetadataHelper::ReleaseObjects();
}
@ -56,109 +65,213 @@ private:
nsRefPtr<IDBMutableFile> mMutableFile;
};
inline
already_AddRefed<nsIFile>
GetFileFor(FileInfo* aFileInfo)
{
FileManager* fileManager = aFileInfo->Manager();
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
NS_ENSURE_TRUE(directory, nullptr);
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aFileInfo);
nsCOMPtr<nsIFile> file = fileManager->GetFileForId(directory,
aFileInfo->Id());
NS_ENSURE_TRUE(file, nullptr);
FileManager* fileManager = aFileInfo->Manager();
MOZ_ASSERT(fileManager);
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
if (NS_WARN_IF(!directory)) {
return nullptr;
}
nsCOMPtr<nsIFile> file =
fileManager->GetFileForId(directory, aFileInfo->Id());
if (NS_WARN_IF(!file)) {
return nullptr;
}
return file.forget();
}
} // anonymous namespace
namespace mozilla {
namespace dom {
namespace indexedDB {
IDBMutableFile::IDBMutableFile(IDBDatabase* aOwner)
: DOMEventTargetHelper(aOwner)
IDBMutableFile::IDBMutableFile(IDBDatabase* aDatabase,
const nsAString& aName,
const nsAString& aType,
already_AddRefed<FileInfo> aFileInfo,
const nsACString& aGroup,
const nsACString& aOrigin,
const nsACString& aStorageId,
PersistenceType aPersistenceType,
already_AddRefed<nsIFile> aFile)
: DOMEventTargetHelper(aDatabase)
, mDatabase(aDatabase)
, mFileInfo(aFileInfo)
, mGroup(aGroup)
, mOrigin(aOrigin)
, mPersistenceType(aPersistenceType)
, mInvalidated(false)
{
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mDatabase);
MOZ_ASSERT(mFileInfo);
mName = aName;
mType = aType;
mFile = aFile;
mStorageId = aStorageId;
mFileName.AppendInt(mFileInfo->Id());
MOZ_ASSERT(mFile);
mDatabase->NoteLiveMutableFile(this);
}
IDBMutableFile::~IDBMutableFile()
{
// XXX This is always in the main process but it sometimes happens too late in
// shutdown and the IndexedDatabaseManager has already been torn down.
// MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
if (mDatabase) {
mDatabase->NoteFinishedMutableFile(this);
}
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(IDBMutableFile, DOMEventTargetHelper,
mDatabase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBMutableFile)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(IDBMutableFile, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(IDBMutableFile, DOMEventTargetHelper)
// static
already_AddRefed<IDBMutableFile>
IDBMutableFile::Create(const nsAString& aName,
IDBMutableFile::Create(IDBDatabase* aDatabase,
const nsAString& aName,
const nsAString& aType,
IDBDatabase* aDatabase,
already_AddRefed<FileInfo> aFileInfo)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<FileInfo> fileInfo(aFileInfo);
NS_ASSERTION(fileInfo, "Null pointer!");
MOZ_ASSERT(fileInfo);
nsRefPtr<IDBMutableFile> newFile = new IDBMutableFile(aDatabase);
PrincipalInfo* principalInfo = aDatabase->Factory()->GetPrincipalInfo();
MOZ_ASSERT(principalInfo);
newFile->mName = aName;
newFile->mType = aType;
nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(*principalInfo);
if (NS_WARN_IF(!principal)) {
return nullptr;
}
newFile->mFile = GetFileFor(fileInfo);
NS_ENSURE_TRUE(newFile->mFile, nullptr);
nsCString group;
nsCString origin;
if (NS_WARN_IF(NS_FAILED(QuotaManager::GetInfoFromPrincipal(principal,
&group,
&origin,
nullptr,
nullptr)))) {
return nullptr;
}
newFile->mStorageId = aDatabase->Id();
newFile->mFileName.AppendInt(fileInfo->Id());
const DatabaseSpec* spec = aDatabase->Spec();
MOZ_ASSERT(spec);
newFile->mDatabase = aDatabase;
fileInfo.swap(newFile->mFileInfo);
PersistenceType persistenceType = spec->metadata().persistenceType();
nsCString storageId;
QuotaManager::GetStorageId(persistenceType,
origin,
Client::IDB,
aDatabase->Name(),
storageId);
nsCOMPtr<nsIFile> file = GetFileFor(fileInfo);
if (NS_WARN_IF(!file)) {
return nullptr;
}
nsRefPtr<IDBMutableFile> newFile =
new IDBMutableFile(aDatabase,
aName,
aType,
fileInfo.forget(),
group,
origin,
storageId,
persistenceType,
file.forget());
return newFile.forget();
}
void
IDBMutableFile::Invalidate()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mInvalidated);
mInvalidated = true;
}
NS_IMPL_ADDREF_INHERITED(IDBMutableFile, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(IDBMutableFile, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBMutableFile)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBMutableFile)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBMutableFile,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDatabase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBMutableFile,
DOMEventTargetHelper)
MOZ_ASSERT(tmp->mDatabase);
tmp->mDatabase->NoteFinishedMutableFile(tmp);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDatabase)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
bool
IDBMutableFile::IsInvalid()
{
return mDatabase->IsInvalidated();
return mInvalidated;
}
nsIOfflineStorage*
IDBMutableFile::Storage()
{
return mDatabase;
MOZ_CRASH("Don't call me!");
}
already_AddRefed<nsISupports>
IDBMutableFile::CreateStream(bool aReadOnly)
{
PersistenceType persistenceType = mDatabase->Type();
const nsACString& group = mDatabase->Group();
const nsACString& origin = mDatabase->Origin();
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
nsCOMPtr<nsISupports> result;
if (aReadOnly) {
nsRefPtr<FileInputStream> stream =
FileInputStream::Create(persistenceType, group, origin, mFile, -1, -1,
FileInputStream::Create(mPersistenceType,
mGroup,
mOrigin,
mFile,
-1,
-1,
nsIFileInputStream::DEFER_OPEN);
result = NS_ISUPPORTS_CAST(nsIFileInputStream*, stream);
}
else {
} else {
nsRefPtr<FileStream> stream =
FileStream::Create(persistenceType, group, origin, mFile, -1, -1,
FileStream::Create(mPersistenceType,
mGroup,
mOrigin,
mFile,
-1,
-1,
nsIFileStream::DEFER_OPEN);
result = NS_ISUPPORTS_CAST(nsIFileStream*, stream);
}
NS_ENSURE_TRUE(result, nullptr);
if (NS_WARN_IF(!result)) {
return nullptr;
}
return result.forget();
}
@ -166,33 +279,37 @@ IDBMutableFile::CreateStream(bool aReadOnly)
void
IDBMutableFile::SetThreadLocals()
{
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
MOZ_ASSERT(mDatabase->GetOwner(), "Should have owner!");
QuotaManager::SetCurrentWindow(mDatabase->GetOwner());
}
void
IDBMutableFile::UnsetThreadLocals()
{
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
QuotaManager::SetCurrentWindow(nullptr);
}
already_AddRefed<nsIDOMFile>
IDBMutableFile::CreateFileObject(IDBFileHandle* aFileHandle, uint32_t aFileSize)
{
nsCOMPtr<nsIDOMFile> fileSnapshot = new DOMFile(
new FileImplSnapshot(mName, mType, aFileSize, mFile, aFileHandle,
mFileInfo));
return fileSnapshot.forget();
}
// virtual
JSObject*
IDBMutableFile::WrapObject(JSContext* aCx)
{
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
return IDBMutableFileBinding::Wrap(aCx, this);
}
IDBDatabase*
IDBMutableFile::Database() const
{
MOZ_ASSERT(NS_IsMainThread());
return mDatabase;
}
already_AddRefed<IDBFileHandle>
IDBMutableFile::Open(FileMode aMode, ErrorResult& aError)
{
@ -213,6 +330,31 @@ IDBMutableFile::Open(FileMode aMode, ErrorResult& aError)
return fileHandle.forget();
}
int64_t
IDBMutableFile::GetFileId() const
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mFileInfo);
return mFileInfo->Id();
}
already_AddRefed<nsIDOMFile>
IDBMutableFile::CreateFileObject(IDBFileHandle* aFileHandle,
MetadataParameters* aMetadataParams)
{
nsRefPtr<DOMFileImpl> impl =
new FileImplSnapshot(mName,
mType,
aMetadataParams,
mFile,
aFileHandle,
mFileInfo);
nsCOMPtr<nsIDOMFile> fileSnapshot = new DOMFile(impl);
return fileSnapshot.forget();
}
already_AddRefed<DOMRequest>
IDBMutableFile::GetFile(ErrorResult& aError)
{
@ -227,10 +369,11 @@ IDBMutableFile::GetFile(ErrorResult& aError)
IDBFileHandle::Create(FileMode::Readonly, FileHandleBase::PARALLEL, this);
nsRefPtr<IDBFileRequest> request =
IDBFileRequest::Create(GetOwner(), fileHandle, /* aWrapAsDOMRequest */
true);
IDBFileRequest::Create(GetOwner(),
fileHandle,
/* aWrapAsDOMRequest */ true);
nsRefPtr<MetadataParameters> params = new MetadataParameters(true, false);
nsRefPtr<MetadataParameters> params = new MetadataParameters(true, true);
nsRefPtr<GetFileHelper> helper =
new GetFileHelper(fileHandle, request, params, this);
@ -244,10 +387,6 @@ IDBMutableFile::GetFile(ErrorResult& aError)
return request.forget();
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
nsresult
GetFileHelper::GetSuccessResult(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal)
@ -257,7 +396,7 @@ GetFileHelper::GetSuccessResult(JSContext* aCx,
auto fileHandle = static_cast<IDBFileHandle*>(mFileHandle.get());
nsCOMPtr<nsIDOMFile> domFile =
mMutableFile->CreateFileObject(fileHandle, mParams->Size());
mMutableFile->CreateFileObject(fileHandle, mParams);
nsresult rv =
nsContentUtils::WrapNative(aCx, domFile, &NS_GET_IID(nsIDOMFile), aVal);
@ -267,3 +406,7 @@ GetFileHelper::GetSuccessResult(JSContext* aCx,
return NS_OK;
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -8,13 +8,13 @@
#define mozilla_dom_indexeddb_idbmutablefile_h__
#include "js/TypeDecls.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/FileModeBinding.h"
#include "mozilla/dom/indexedDB/FileInfo.h"
#include "mozilla/dom/MutableFile.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/FileModeBinding.h"
#include "mozilla/dom/MutableFile.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
@ -28,23 +28,39 @@ class ErrorResult;
namespace dom {
class DOMRequest;
class MetadataParameters;
namespace indexedDB {
class FileInfo;
class IDBDatabase;
class IDBFileHandle;
class IDBMutableFile MOZ_FINAL : public DOMEventTargetHelper,
public MutableFileBase
class IDBMutableFile MOZ_FINAL
: public DOMEventTargetHelper
, public MutableFileBase
{
typedef mozilla::dom::MetadataParameters MetadataParameters;
typedef mozilla::dom::quota::PersistenceType PersistenceType;
nsString mName;
nsString mType;
nsRefPtr<IDBDatabase> mDatabase;
nsRefPtr<FileInfo> mFileInfo;
const nsCString mGroup;
const nsCString mOrigin;
const PersistenceType mPersistenceType;
Atomic<bool> mInvalidated;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBMutableFile, DOMEventTargetHelper)
static already_AddRefed<IDBMutableFile>
Create(const nsAString& aName, const nsAString& aType,
IDBDatabase* aDatabase, already_AddRefed<FileInfo> aFileInfo);
Create(IDBDatabase* aDatabase,
const nsAString& aName,
const nsAString& aType,
already_AddRefed<FileInfo> aFileInfo);
const nsAString&
Name() const
@ -59,10 +75,7 @@ public:
}
int64_t
GetFileId() const
{
return mFileInfo->Id();
}
GetFileId() const;
FileInfo*
GetFileInfo() const
@ -70,6 +83,16 @@ public:
return mFileInfo;
}
already_AddRefed<nsIDOMFile>
CreateFileObject(IDBFileHandle* aFileHandle,
MetadataParameters* aMetadataParams);
void
Invalidate();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBMutableFile, DOMEventTargetHelper)
virtual bool
IsInvalid() MOZ_OVERRIDE;
@ -85,9 +108,6 @@ public:
virtual void
UnsetThreadLocals() MOZ_OVERRIDE;
already_AddRefed<nsIDOMFile>
CreateFileObject(IDBFileHandle* aFileHandle, uint32_t aFileSize);
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
@ -112,12 +132,7 @@ public:
}
IDBDatabase*
Database()
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
return mDatabase;
}
Database() const;
already_AddRefed<IDBFileHandle>
Open(FileMode aMode, ErrorResult& aError);
@ -129,14 +144,17 @@ public:
IMPL_EVENT_HANDLER(error)
private:
explicit IDBMutableFile(IDBDatabase* aOwner);
IDBMutableFile(IDBDatabase* aDatabase,
const nsAString& aName,
const nsAString& aType,
already_AddRefed<FileInfo> aFileInfo,
const nsACString& aGroup,
const nsACString& aOrigin,
const nsACString& aStorageId,
PersistenceType aPersistenceType,
already_AddRefed<nsIFile> aFile);
~IDBMutableFile();
nsString mName;
nsString mType;
nsRefPtr<IDBDatabase> mDatabase;
nsRefPtr<FileInfo> mFileInfo;
};
} // namespace indexedDB

File diff suppressed because it is too large Load Diff

View File

@ -7,61 +7,68 @@
#ifndef mozilla_dom_indexeddb_idbobjectstore_h__
#define mozilla_dom_indexeddb_idbobjectstore_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "js/TypeDecls.h"
#include "js/RootingAPI.h"
#include "mozilla/dom/IDBCursorBinding.h"
#include "mozilla/dom/IDBIndexBinding.h"
#include "mozilla/dom/IDBObjectStoreBinding.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "MainThreadUtils.h"
#include "nsISupports.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "mozilla/dom/indexedDB/IDBTransaction.h"
#include "mozilla/dom/indexedDB/KeyPath.h"
class nsIDOMBlob;
class nsIScriptContext;
struct JSClass;
class nsPIDOMWindow;
namespace mozilla {
class ErrorResult;
namespace dom {
class DOMStringList;
class nsIContentParent;
class PBlobChild;
class PBlobParent;
}
}
template <typename> class Sequence;
BEGIN_INDEXEDDB_NAMESPACE
namespace indexedDB {
class AsyncConnectionHelper;
class FileManager;
class IDBCursor;
class IDBKeyRange;
class IDBRequest;
class IndexedDBObjectStoreChild;
class IndexedDBObjectStoreParent;
class IDBTransaction;
class IndexUpdateInfo;
class Key;
class KeyPath;
class ObjectStoreSpec;
struct StructuredCloneFile;
struct StructuredCloneReadInfo;
struct IndexInfo;
struct IndexUpdateInfo;
struct ObjectStoreInfo;
struct MutableFileData;
struct BlobOrFileData;
class IDBObjectStore MOZ_FINAL : public nsISupports,
public nsWrapperCache
class IDBObjectStore MOZ_FINAL
: public nsISupports
, public nsWrapperCache
{
static const JSClass sDummyPropJSClass;
nsRefPtr<IDBTransaction> mTransaction;
JS::Heap<JS::Value> mCachedKeyPath;
// This normally points to the ObjectStoreSpec owned by the parent IDBDatabase
// object. However, if this objectStore is part of a versionchange transaction
// and it gets deleted then the spec is copied into mDeletedSpec and mSpec is
// set to point at mDeletedSpec.
const ObjectStoreSpec* mSpec;
nsAutoPtr<ObjectStoreSpec> mDeletedSpec;
nsTArray<nsRefPtr<IDBIndex>> mIndexes;
const int64_t mId;
bool mRooted;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBObjectStore)
struct StructuredCloneWriteInfo;
static already_AddRefed<IDBObjectStore>
Create(IDBTransaction* aTransaction,
ObjectStoreInfo* aInfo,
const nsACString& aDatabaseId,
bool aCreating);
Create(IDBTransaction* aTransaction, const ObjectStoreSpec& aSpec);
static nsresult
AppendIndexUpdateInfo(int64_t aIndexID,
@ -72,214 +79,62 @@ public:
JS::Handle<JS::Value> aObject,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
static nsresult
UpdateIndexes(IDBTransaction* aTransaction,
int64_t aObjectStoreId,
const Key& aObjectStoreKey,
bool aOverwrite,
int64_t aObjectDataId,
const nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
static nsresult
GetStructuredCloneReadInfoFromStatement(mozIStorageStatement* aStatement,
uint32_t aDataIndex,
uint32_t aFileIdsIndex,
IDBDatabase* aDatabase,
StructuredCloneReadInfo& aInfo);
static void
ClearCloneReadInfo(StructuredCloneReadInfo& aReadInfo);
static void
ClearCloneWriteInfo(StructuredCloneWriteInfo& aWriteInfo);
static bool
DeserializeValue(JSContext* aCx,
StructuredCloneReadInfo& aCloneReadInfo,
JS::MutableHandle<JS::Value> aValue);
static bool
SerializeValue(JSContext* aCx,
StructuredCloneWriteInfo& aCloneWriteInfo,
JS::Handle<JS::Value> aValue);
DeserializeIndexValue(JSContext* aCx,
StructuredCloneReadInfo& aCloneReadInfo,
JS::MutableHandle<JS::Value> aValue);
template <class DeserializationTraits>
static JSObject*
StructuredCloneReadCallback(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32_t aTag,
uint32_t aData,
void* aClosure);
static bool
StructuredCloneWriteCallback(JSContext* aCx,
JSStructuredCloneWriter* aWriter,
JS::Handle<JSObject*> aObj,
void* aClosure);
static nsresult
ConvertFileIdsToArray(const nsAString& aFileIds,
nsTArray<int64_t>& aResult);
// Called only in the main process.
static nsresult
ConvertBlobsToActors(nsIContentParent* aContentParent,
FileManager* aFileManager,
const nsTArray<StructuredCloneFile>& aFiles,
InfallibleTArray<PBlobParent*>& aActors);
// Called only in the child process.
static void
ConvertActorsToBlobs(const InfallibleTArray<PBlobChild*>& aActors,
nsTArray<StructuredCloneFile>& aFiles);
const nsString& Name() const
static const JSClass*
DummyPropClass()
{
return mName;
return &sDummyPropJSClass;
}
bool IsAutoIncrement() const
{
return mAutoIncrement;
}
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
bool IsWriteAllowed() const
int64_t
Id() const
{
return mTransaction->IsWriteAllowed();
}
AssertIsOnOwningThread();
int64_t Id() const
{
NS_ASSERTION(mId != INT64_MIN, "Don't ask for this yet!");
return mId;
}
const KeyPath& GetKeyPath() const
{
return mKeyPath;
}
const nsString&
Name() const;
const bool HasValidKeyPath() const
{
return mKeyPath.IsValid();
}
bool
AutoIncrement() const;
IDBTransaction* Transaction()
{
return mTransaction;
}
const KeyPath&
GetKeyPath() const;
ObjectStoreInfo* Info()
{
return mInfo;
}
bool
HasValidKeyPath() const;
void
SetActor(IndexedDBObjectStoreChild* aActorChild)
{
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
mActorChild = aActorChild;
}
void
SetActor(IndexedDBObjectStoreParent* aActorParent)
{
NS_ASSERTION(!aActorParent || !mActorParent,
"Shouldn't have more than one!");
mActorParent = aActorParent;
}
IndexedDBObjectStoreChild*
GetActorChild() const
{
return mActorChild;
}
IndexedDBObjectStoreParent*
GetActorParent() const
{
return mActorParent;
}
already_AddRefed<IDBIndex>
CreateIndexInternal(const IndexInfo& aInfo,
ErrorResult& aRv);
nsresult AddOrPutInternal(
const SerializedStructuredCloneWriteInfo& aCloneWriteInfo,
const Key& aKey,
const InfallibleTArray<IndexUpdateInfo>& aUpdateInfoArray,
const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs,
bool aOverwrite,
IDBRequest** _retval);
already_AddRefed<IDBRequest>
GetInternal(IDBKeyRange* aKeyRange,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
GetAllInternal(IDBKeyRange* aKeyRange,
uint32_t aLimit,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
GetAllKeysInternal(IDBKeyRange* aKeyRange,
uint32_t aLimit,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
DeleteInternal(IDBKeyRange* aKeyRange,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
CountInternal(IDBKeyRange* aKeyRange,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
OpenCursorInternal(IDBKeyRange* aKeyRange,
size_t aDirection,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
OpenKeyCursorInternal(IDBKeyRange* aKeyRange,
size_t aDirection,
ErrorResult& aRv);
nsresult
OpenCursorFromChildProcess(
IDBRequest* aRequest,
size_t aDirection,
const Key& aKey,
const SerializedStructuredCloneReadInfo& aCloneInfo,
nsTArray<StructuredCloneFile>& aBlobs,
IDBCursor** _retval);
nsresult
OpenCursorFromChildProcess(IDBRequest* aRequest,
size_t aDirection,
const Key& aKey,
IDBCursor** _retval);
void
SetInfo(ObjectStoreInfo* aInfo);
static const JSClass sDummyPropJSClass;
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
IDBTransaction*
GetParentObject() const
{
return mTransaction;
}
nsPIDOMWindow*
GetParentObject() const;
void
GetName(nsString& aName) const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
aName.Assign(mName);
AssertIsOnOwningThread();
aName = Name();
}
void
@ -287,38 +142,38 @@ public:
ErrorResult& aRv);
already_AddRefed<DOMStringList>
GetIndexNames(ErrorResult& aRv);
IndexNames();
IDBTransaction*
Transaction() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
return mTransaction;
}
bool
AutoIncrement() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return mAutoIncrement;
}
already_AddRefed<IDBRequest>
Put(JSContext* aCx, JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aKey, ErrorResult& aRv)
Add(JSContext* aCx,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aKey,
ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return AddOrPut(aCx, aValue, aKey, true, aRv);
}
AssertIsOnOwningThread();
already_AddRefed<IDBRequest>
Add(JSContext* aCx, JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aKey, ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return AddOrPut(aCx, aValue, aKey, false, aRv);
}
already_AddRefed<IDBRequest>
Put(JSContext* aCx,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aKey,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
return AddOrPut(aCx, aValue, aKey, true, aRv);
}
already_AddRefed<IDBRequest>
Delete(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
@ -328,18 +183,19 @@ public:
already_AddRefed<IDBRequest>
Clear(ErrorResult& aRv);
already_AddRefed<IDBRequest>
OpenCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection, ErrorResult& aRv);
already_AddRefed<IDBIndex>
CreateIndex(JSContext* aCx,
const nsAString& aName,
const nsAString& aKeyPath,
const IDBIndexParameters& aOptionalParameters,
ErrorResult& aRv);
already_AddRefed<IDBIndex>
CreateIndex(JSContext* aCx, const nsAString& aName, const nsAString& aKeyPath,
const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
already_AddRefed<IDBIndex>
CreateIndex(JSContext* aCx, const nsAString& aName,
CreateIndex(JSContext* aCx,
const nsAString& aName,
const Sequence<nsString>& aKeyPath,
const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
const IDBIndexParameters& aOptionalParameters,
ErrorResult& aRv);
already_AddRefed<IDBIndex>
Index(const nsAString& aName, ErrorResult &aRv);
@ -348,70 +204,116 @@ public:
DeleteIndex(const nsAString& aIndexName, ErrorResult& aRv);
already_AddRefed<IDBRequest>
Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
Count(JSContext* aCx,
JS::Handle<JS::Value> aKey,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit, ErrorResult& aRv);
GetAll(JSContext* aCx,
JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
return GetAllInternal(/* aKeysOnly */ false, aCx, aKey, aLimit, aRv);
}
already_AddRefed<IDBRequest>
GetAllKeys(JSContext* aCx, JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit, ErrorResult& aRv);
GetAllKeys(JSContext* aCx,
JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
return GetAllInternal(/* aKeysOnly */ true, aCx, aKey, aLimit, aRv);
}
already_AddRefed<IDBRequest>
OpenKeyCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection, ErrorResult& aRv);
OpenCursor(JSContext* aCx,
JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
return OpenCursorInternal(/* aKeysOnly */ false, aCx, aRange, aDirection,
aRv);
}
already_AddRefed<IDBRequest>
OpenKeyCursor(JSContext* aCx,
JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
return OpenCursorInternal(/* aKeysOnly */ true, aCx, aRange, aDirection,
aRv);
}
void
RefreshSpec(bool aMayDelete);
const ObjectStoreSpec&
Spec() const;
void
NoteDeletion();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBObjectStore)
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
private:
IDBObjectStore(IDBTransaction* aTransaction, const ObjectStoreSpec* aSpec);
protected:
IDBObjectStore();
~IDBObjectStore();
nsresult GetAddInfo(JSContext* aCx,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aKeyVal,
StructuredCloneWriteInfo& aCloneWriteInfo,
Key& aKey,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
nsresult
GetAddInfo(JSContext* aCx,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aKeyVal,
StructuredCloneWriteInfo& aCloneWriteInfo,
Key& aKey,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
already_AddRefed<IDBRequest>
AddOrPut(JSContext* aCx, JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aKey, bool aOverwrite,
AddOrPut(JSContext* aCx,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aKey,
bool aOverwrite,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
GetAllInternal(bool aKeysOnly,
JSContext* aCx,
JS::Handle<JS::Value> aKey,
const Optional<uint32_t>& aLimit,
ErrorResult& aRv);
already_AddRefed<IDBIndex>
CreateIndex(JSContext* aCx, const nsAString& aName, KeyPath& aKeyPath,
const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
CreateIndexInternal(JSContext* aCx,
const nsAString& aName,
const KeyPath& aKeyPath,
const IDBIndexParameters& aOptionalParameters,
ErrorResult& aRv);
static void
ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer);
static bool
ReadMutableFile(JSStructuredCloneReader* aReader,
MutableFileData* aRetval);
static bool
ReadBlobOrFile(JSStructuredCloneReader* aReader,
uint32_t aTag,
BlobOrFileData* aRetval);
private:
nsRefPtr<IDBTransaction> mTransaction;
int64_t mId;
nsString mName;
KeyPath mKeyPath;
JS::Heap<JS::Value> mCachedKeyPath;
bool mRooted;
bool mAutoIncrement;
nsCString mDatabaseId;
nsRefPtr<ObjectStoreInfo> mInfo;
nsTArray<nsRefPtr<IDBIndex> > mCreatedIndexes;
IndexedDBObjectStoreChild* mActorChild;
IndexedDBObjectStoreParent* mActorParent;
already_AddRefed<IDBRequest>
OpenCursorInternal(bool aKeysOnly,
JSContext* aCx,
JS::Handle<JS::Value> aRange,
IDBCursorDirection aDirection,
ErrorResult& aRv);
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbobjectstore_h__

View File

@ -6,78 +6,88 @@
#include "IDBRequest.h"
#include "nsIScriptContext.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/ErrorEventBinding.h"
#include "mozilla/dom/IDBOpenDBRequestBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/UnionTypes.h"
#include "nsComponentManagerUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsDOMJSUtils.h"
#include "nsContentUtils.h"
#include "nsJSUtils.h"
#include "nsPIDOMWindow.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "nsWrapperCacheInlines.h"
#include "AsyncConnectionHelper.h"
#include "BackgroundChildImpl.h"
#include "IDBCursor.h"
#include "IDBDatabase.h"
#include "IDBEvents.h"
#include "IDBFactory.h"
#include "IDBIndex.h"
#include "IDBObjectStore.h"
#include "IDBTransaction.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/ErrorEventBinding.h"
#include "mozilla/dom/IDBOpenDBRequestBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/UnionTypes.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsIScriptContext.h"
#include "nsJSUtils.h"
#include "nsPIDOMWindow.h"
#include "nsString.h"
#include "ReportInternalError.h"
namespace {
namespace mozilla {
namespace dom {
namespace indexedDB {
#ifdef MOZ_ENABLE_PROFILER_SPS
uint64_t gNextRequestSerialNumber = 1;
#endif
} // anonymous namespace
USING_INDEXEDDB_NAMESPACE
using mozilla::dom::OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
using mozilla::dom::ErrorEventInit;
using namespace mozilla;
using namespace mozilla::ipc;
IDBRequest::IDBRequest(IDBDatabase* aDatabase)
: IDBWrapperCache(aDatabase),
mResultVal(JSVAL_VOID),
mActorParent(nullptr),
#ifdef MOZ_ENABLE_PROFILER_SPS
mSerialNumber(gNextRequestSerialNumber++),
#endif
mErrorCode(NS_OK),
mLineNo(0),
mHaveResultOrErrorCode(false)
: IDBWrapperCache(aDatabase)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(aDatabase);
aDatabase->AssertIsOnOwningThread();
InitMembers();
}
IDBRequest::IDBRequest(nsPIDOMWindow* aOwner)
: IDBWrapperCache(aOwner),
mResultVal(JSVAL_VOID),
mActorParent(nullptr),
#ifdef MOZ_ENABLE_PROFILER_SPS
mSerialNumber(gNextRequestSerialNumber++),
#endif
mErrorCode(NS_OK),
mLineNo(0),
mHaveResultOrErrorCode(false)
: IDBWrapperCache(aOwner)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
InitMembers();
}
IDBRequest::~IDBRequest()
{
mResultVal = JSVAL_VOID;
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
}
#ifdef DEBUG
void
IDBRequest::AssertIsOnOwningThread() const
{
MOZ_ASSERT(mOwningThread);
MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
}
#endif // DEBUG
void
IDBRequest::InitMembers()
{
#ifdef DEBUG
mOwningThread = PR_GetCurrentThread();
#endif
AssertIsOnOwningThread();
mResultVal.setUndefined();
mErrorCode = NS_OK;
mLineNo = 0;
mHaveResultOrErrorCode = false;
#ifdef MOZ_ENABLE_PROFILER_SPS
{
BackgroundChildImpl::ThreadLocal* threadLocal =
BackgroundChildImpl::GetThreadLocalForCurrentThread();
MOZ_ASSERT(threadLocal);
mSerialNumber = threadLocal->mNextRequestSerialNumber++;
}
#endif
}
// static
@ -85,16 +95,15 @@ already_AddRefed<IDBRequest>
IDBRequest::Create(IDBDatabase* aDatabase,
IDBTransaction* aTransaction)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<IDBRequest> request(new IDBRequest(aDatabase));
MOZ_ASSERT(aDatabase);
aDatabase->AssertIsOnOwningThread();
nsRefPtr<IDBRequest> request = new IDBRequest(aDatabase);
request->mTransaction = aTransaction;
request->SetScriptOwner(aDatabase->GetScriptOwner());
if (!aDatabase->Factory()->FromIPC()) {
request->CaptureCaller();
}
request->CaptureCaller();
return request.forget();
}
@ -105,6 +114,9 @@ IDBRequest::Create(IDBObjectStore* aSourceAsObjectStore,
IDBDatabase* aDatabase,
IDBTransaction* aTransaction)
{
MOZ_ASSERT(aSourceAsObjectStore);
aSourceAsObjectStore->AssertIsOnOwningThread();
nsRefPtr<IDBRequest> request = Create(aDatabase, aTransaction);
request->mSourceAsObjectStore = aSourceAsObjectStore;
@ -118,6 +130,9 @@ IDBRequest::Create(IDBIndex* aSourceAsIndex,
IDBDatabase* aDatabase,
IDBTransaction* aTransaction)
{
MOZ_ASSERT(aSourceAsIndex);
aSourceAsIndex->AssertIsOnOwningThread();
nsRefPtr<IDBRequest> request = Create(aDatabase, aTransaction);
request->mSourceAsIndex = aSourceAsIndex;
@ -125,31 +140,24 @@ IDBRequest::Create(IDBIndex* aSourceAsIndex,
return request.forget();
}
#ifdef DEBUG
void
IDBRequest::AssertSourceIsCorrect() const
IDBRequest::GetSource(
Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const
{
// At most one of mSourceAs* is allowed to be non-null. Check that by
// summing the double negation of each one and asserting the sum is at most
// 1.
AssertIsOnOwningThread();
MOZ_ASSERT(!!mSourceAsObjectStore + !!mSourceAsIndex + !!mSourceAsCursor <= 1);
}
#endif
MOZ_ASSERT_IF(mSourceAsObjectStore, !mSourceAsIndex);
MOZ_ASSERT_IF(mSourceAsIndex, !mSourceAsObjectStore);
MOZ_ASSERT_IF(mSourceAsCursor, mSourceAsObjectStore || mSourceAsIndex);
void
IDBRequest::GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const
{
MOZ_ASSERT(NS_IsMainThread());
AssertSourceIsCorrect();
if (mSourceAsObjectStore) {
// Always check cursor first since cursor requests hold both the cursor and
// the objectStore or index the cursor came from.
if (mSourceAsCursor) {
aSource.SetValue().SetAsIDBCursor() = mSourceAsCursor;
} else if (mSourceAsObjectStore) {
aSource.SetValue().SetAsIDBObjectStore() = mSourceAsObjectStore;
} else if (mSourceAsIndex) {
aSource.SetValue().SetAsIDBIndex() = mSourceAsIndex;
} else if (mSourceAsCursor) {
aSource.SetValue().SetAsIDBCursor() = mSourceAsCursor;
} else {
aSource.SetNull();
}
@ -158,116 +166,63 @@ IDBRequest::GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSour
void
IDBRequest::Reset()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mResultVal = JSVAL_VOID;
AssertIsOnOwningThread();
mResultVal.setUndefined();
mHaveResultOrErrorCode = false;
mError = nullptr;
}
nsresult
IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!");
NS_ASSERTION(mResultVal.isUndefined(), "Should be undefined!");
mHaveResultOrErrorCode = true;
nsresult rv = aHelper->GetResultCode();
// If the request failed then set the error code and return.
if (NS_FAILED(rv)) {
SetError(rv);
return NS_OK;
}
// See if our window is still valid. If not then we're going to pretend that
// we never completed.
if (NS_FAILED(CheckInnerWindowCorrectness())) {
return NS_OK;
}
// Otherwise we need to get the result from the helper.
AutoJSAPI jsapi;
Maybe<JSAutoCompartment> ac;
if (GetScriptOwner()) {
// If we have a script owner we want the SafeJSContext and then to enter
// the script owner's compartment.
jsapi.Init();
ac.emplace(jsapi.cx(), GetScriptOwner());
} else {
// Otherwise our owner is a window and we use that to initialize.
if (!jsapi.InitWithLegacyErrorReporting(GetOwner())) {
IDB_WARNING("Failed to initialise AutoJSAPI!");
rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
SetError(rv);
return rv;
}
}
JSContext* cx = jsapi.cx();
AssertIsRooted();
JS::Rooted<JS::Value> value(cx);
rv = aHelper->GetSuccessResult(cx, &value);
if (NS_FAILED(rv)) {
NS_WARNING("GetSuccessResult failed!");
}
if (NS_SUCCEEDED(rv)) {
mError = nullptr;
mResultVal = value;
}
else {
SetError(rv);
mResultVal = JSVAL_VOID;
}
return rv;
}
void
IDBRequest::NotifyHelperSentResultsToChildProcess(nsresult aRv)
IDBRequest::DispatchNonTransactionError(nsresult aErrorCode)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!");
NS_ASSERTION(mResultVal.isUndefined(), "Should be undefined!");
AssertIsOnOwningThread();
MOZ_ASSERT(NS_FAILED(aErrorCode));
MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_INDEXEDDB);
// See if our window is still valid. If not then we're going to pretend that
// we never completed.
if (NS_FAILED(CheckInnerWindowCorrectness())) {
SetError(aErrorCode);
// Make an error event and fire it at the target.
nsCOMPtr<nsIDOMEvent> event =
CreateGenericEvent(this,
nsDependentString(kErrorEventType),
eDoesBubble,
eCancelable);
if (NS_WARN_IF(!event)) {
return;
}
mHaveResultOrErrorCode = true;
if (NS_FAILED(aRv)) {
SetError(aRv);
}
bool ignored;
NS_WARN_IF(NS_FAILED(DispatchEvent(event, &ignored)));
}
void
IDBRequest::SetError(nsresult aRv)
{
NS_ASSERTION(NS_FAILED(aRv), "Er, what?");
NS_ASSERTION(!mError, "Already have an error?");
AssertIsOnOwningThread();
MOZ_ASSERT(NS_FAILED(aRv));
MOZ_ASSERT(NS_ERROR_GET_MODULE(aRv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
MOZ_ASSERT(!mError);
mHaveResultOrErrorCode = true;
mError = new mozilla::dom::DOMError(GetOwner(), aRv);
mError = new DOMError(GetOwner(), aRv);
mErrorCode = aRv;
mResultVal = JSVAL_VOID;
mResultVal.setUndefined();
}
#ifdef DEBUG
nsresult
IDBRequest::GetErrorCode() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(mHaveResultOrErrorCode, "Don't call me yet!");
AssertIsOnOwningThread();
MOZ_ASSERT(mHaveResultOrErrorCode);
return mErrorCode;
}
#endif
#endif // DEBUG
void
IDBRequest::CaptureCaller()
@ -277,7 +232,6 @@ IDBRequest::CaptureCaller()
const char* filename = nullptr;
uint32_t lineNo = 0;
if (!nsJSUtils::GetCallingLocation(cx, &filename, &lineNo)) {
NS_WARNING("Failed to get caller.");
return;
}
@ -292,16 +246,25 @@ IDBRequest::FillScriptErrorEvent(ErrorEventInit& aEventInit) const
aEventInit.mFilename = mFilename;
}
mozilla::dom::IDBRequestReadyState
IDBRequestReadyState
IDBRequest::ReadyState() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
if (IsPending()) {
return IDBRequestReadyState::Pending;
}
return IsPending() ?
IDBRequestReadyState::Pending :
IDBRequestReadyState::Done;
}
return IDBRequestReadyState::Done;
void
IDBRequest::SetSource(IDBCursor* aSource)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aSource);
MOZ_ASSERT(mSourceAsObjectStore || mSourceAsIndex);
MOZ_ASSERT(!mSourceAsCursor);
mSourceAsCursor = aSource;
}
JSObject*
@ -314,21 +277,72 @@ void
IDBRequest::GetResult(JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
if (!mHaveResultOrErrorCode) {
// XXX Need a real error code here.
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
JS::ExposeValueToActiveJS(mResultVal);
aResult.set(mResultVal);
}
mozilla::dom::DOMError*
IDBRequest::GetError(mozilla::ErrorResult& aRv)
void
IDBRequest::SetResultCallback(ResultCallback* aCallback)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
MOZ_ASSERT(aCallback);
MOZ_ASSERT(!mHaveResultOrErrorCode);
MOZ_ASSERT(mResultVal.isUndefined());
MOZ_ASSERT(!mError);
// See if our window is still valid.
if (NS_WARN_IF(NS_FAILED(CheckInnerWindowCorrectness()))) {
IDB_REPORT_INTERNAL_ERR();
SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return;
}
AutoJSAPI autoJS;
Maybe<JSAutoCompartment> ac;
if (GetScriptOwner()) {
// If we have a script owner we want the SafeJSContext and then to enter the
// script owner's compartment.
autoJS.Init();
ac.emplace(autoJS.cx(), GetScriptOwner());
} else {
// Otherwise our owner is a window and we use that to initialize.
MOZ_ASSERT(GetOwner());
if (!autoJS.InitWithLegacyErrorReporting(GetOwner())) {
IDB_WARNING("Failed to initialize AutoJSAPI!");
SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return;
}
}
JSContext* cx = autoJS.cx();
AssertIsRooted();
JS::Rooted<JS::Value> result(cx);
nsresult rv = aCallback->GetResult(cx, &result);
if (NS_WARN_IF(NS_FAILED(rv))) {
SetError(rv);
mResultVal.setUndefined();
} else {
mError = nullptr;
mResultVal = result;
}
mHaveResultOrErrorCode = true;
}
DOMError*
IDBRequest::GetError(ErrorResult& aRv)
{
AssertIsOnOwningThread();
if (!mHaveResultOrErrorCode) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
@ -351,7 +365,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
tmp->mResultVal = JSVAL_VOID;
tmp->mResultVal.setUndefined();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsObjectStore)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsIndex)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsCursor)
@ -374,41 +388,60 @@ NS_IMPL_RELEASE_INHERITED(IDBRequest, IDBWrapperCache)
nsresult
IDBRequest::PreHandleEvent(EventChainPreVisitor& aVisitor)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
aVisitor.mCanHandle = true;
aVisitor.mParentTarget = mTransaction;
return NS_OK;
}
IDBOpenDBRequest::IDBOpenDBRequest(nsPIDOMWindow* aOwner)
IDBOpenDBRequest::IDBOpenDBRequest(IDBFactory* aFactory, nsPIDOMWindow* aOwner)
: IDBRequest(aOwner)
, mFactory(aFactory)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
MOZ_ASSERT(aFactory);
// aOwner may be null.
}
IDBOpenDBRequest::~IDBOpenDBRequest()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
}
// static
already_AddRefed<IDBOpenDBRequest>
IDBOpenDBRequest::Create(IDBFactory* aFactory,
nsPIDOMWindow* aOwner,
JS::Handle<JSObject*> aScriptOwner)
IDBOpenDBRequest::CreateForWindow(IDBFactory* aFactory,
nsPIDOMWindow* aOwner,
JS::Handle<JSObject*> aScriptOwner)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aFactory, "Null pointer!");
MOZ_ASSERT(aFactory);
aFactory->AssertIsOnOwningThread();
MOZ_ASSERT(aOwner);
MOZ_ASSERT(aScriptOwner);
nsRefPtr<IDBOpenDBRequest> request = new IDBOpenDBRequest(aOwner);
nsRefPtr<IDBOpenDBRequest> request = new IDBOpenDBRequest(aFactory, aOwner);
request->CaptureCaller();
request->SetScriptOwner(aScriptOwner);
request->mFactory = aFactory;
if (!aFactory->FromIPC()) {
request->CaptureCaller();
}
return request.forget();
}
// static
already_AddRefed<IDBOpenDBRequest>
IDBOpenDBRequest::CreateForJS(IDBFactory* aFactory,
JS::Handle<JSObject*> aScriptOwner)
{
MOZ_ASSERT(aFactory);
aFactory->AssertIsOnOwningThread();
MOZ_ASSERT(aScriptOwner);
nsRefPtr<IDBOpenDBRequest> request = new IDBOpenDBRequest(aFactory, nullptr);
request->CaptureCaller();
request->SetScriptOwner(aScriptOwner);
return request.forget();
}
@ -416,10 +449,9 @@ IDBOpenDBRequest::Create(IDBFactory* aFactory,
void
IDBOpenDBRequest::SetTransaction(IDBTransaction* aTransaction)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
NS_ASSERTION(!aTransaction || !mTransaction,
"Shouldn't have a transaction here!");
MOZ_ASSERT(!aTransaction || !mTransaction);
mTransaction = aTransaction;
}
@ -445,11 +477,20 @@ NS_IMPL_RELEASE_INHERITED(IDBOpenDBRequest, IDBRequest)
nsresult
IDBOpenDBRequest::PostHandleEvent(EventChainPostVisitor& aVisitor)
{
// XXX Fix me!
MOZ_ASSERT(NS_IsMainThread());
return IndexedDatabaseManager::FireWindowOnError(GetOwner(), aVisitor);
}
JSObject*
IDBOpenDBRequest::WrapObject(JSContext* aCx)
{
AssertIsOnOwningThread();
return IDBOpenDBRequestBinding::Wrap(aCx, this);
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -7,72 +7,98 @@
#ifndef mozilla_dom_indexeddb_idbrequest_h__
#define mozilla_dom_indexeddb_idbrequest_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "js/RootingAPI.h"
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/IDBRequestBinding.h"
#include "mozilla/ErrorResult.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
class nsIScriptContext;
class nsPIDOMWindow;
struct PRThread;
namespace mozilla {
class EventChainPostVisitor;
class EventChainPreVisitor;
class ErrorResult;
namespace dom {
class OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
class DOMError;
struct ErrorEventInit;
}
}
template <typename> struct Nullable;
class OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
BEGIN_INDEXEDDB_NAMESPACE
namespace indexedDB {
class HelperBase;
class IDBCursor;
class IDBDatabase;
class IDBFactory;
class IDBIndex;
class IDBObjectStore;
class IDBTransaction;
class IndexedDBRequestParentBase;
class IDBRequest : public IDBWrapperCache
class IDBRequest
: public IDBWrapperCache
{
protected:
// mSourceAsObjectStore and mSourceAsIndex are exclusive and one must always
// be set. mSourceAsCursor is sometimes set also.
nsRefPtr<IDBObjectStore> mSourceAsObjectStore;
nsRefPtr<IDBIndex> mSourceAsIndex;
nsRefPtr<IDBCursor> mSourceAsCursor;
nsRefPtr<IDBTransaction> mTransaction;
#ifdef DEBUG
PRThread* mOwningThread;
#endif
JS::Heap<JS::Value> mResultVal;
nsRefPtr<DOMError> mError;
nsString mFilename;
#ifdef MOZ_ENABLE_PROFILER_SPS
uint64_t mSerialNumber;
#endif
nsresult mErrorCode;
uint32_t mLineNo;
bool mHaveResultOrErrorCode;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBRequest,
IDBWrapperCache)
class ResultCallback;
static
already_AddRefed<IDBRequest> Create(IDBDatabase* aDatabase,
IDBTransaction* aTransaction);
static already_AddRefed<IDBRequest>
Create(IDBDatabase* aDatabase, IDBTransaction* aTransaction);
static
already_AddRefed<IDBRequest> Create(IDBObjectStore* aSource,
IDBDatabase* aDatabase,
IDBTransaction* aTransaction);
static already_AddRefed<IDBRequest>
Create(IDBObjectStore* aSource,
IDBDatabase* aDatabase,
IDBTransaction* aTransaction);
static
already_AddRefed<IDBRequest> Create(IDBIndex* aSource,
IDBDatabase* aDatabase,
IDBTransaction* aTransaction);
static already_AddRefed<IDBRequest>
Create(IDBIndex* aSource,
IDBDatabase* aDatabase,
IDBTransaction* aTransaction);
// nsIDOMEventTarget
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
virtual nsresult
PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
void GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const;
void
GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const;
void Reset();
void
Reset();
nsresult NotifyHelperCompleted(HelperBase* aHelper);
void NotifyHelperSentResultsToChildProcess(nsresult aRv);
void
DispatchNonTransactionError(nsresult aErrorCode);
void SetError(nsresult aRv);
void
SetResultCallback(ResultCallback* aCallback);
void
SetError(nsresult aRv);
nsresult
GetErrorCode() const
@ -84,25 +110,11 @@ public:
}
#endif
DOMError* GetError(ErrorResult& aRv);
DOMError*
GetError(ErrorResult& aRv);
void
SetActor(IndexedDBRequestParentBase* aActorParent)
{
NS_ASSERTION(!aActorParent || !mActorParent,
"Shouldn't have more than one!");
mActorParent = aActorParent;
}
IndexedDBRequestParentBase*
GetActorParent() const
{
return mActorParent;
}
void CaptureCaller();
void FillScriptErrorEvent(ErrorEventInit& aEventInit) const;
FillScriptErrorEvent(ErrorEventInit& aEventInit) const;
bool
IsPending() const
@ -118,11 +130,6 @@ public:
}
#endif
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
nsPIDOMWindow*
GetParentObject() const
{
@ -142,66 +149,87 @@ public:
IDBTransaction*
GetTransaction() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AssertIsOnOwningThread();
return mTransaction;
}
IDBRequestReadyState
ReadyState() const;
void
SetSource(IDBCursor* aSource);
IMPL_EVENT_HANDLER(success);
IMPL_EVENT_HANDLER(error);
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBRequest,
IDBWrapperCache)
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
protected:
explicit IDBRequest(IDBDatabase* aDatabase);
explicit IDBRequest(nsPIDOMWindow* aOwner);
~IDBRequest();
// At most one of these three fields can be non-null.
nsRefPtr<IDBObjectStore> mSourceAsObjectStore;
nsRefPtr<IDBIndex> mSourceAsIndex;
nsRefPtr<IDBCursor> mSourceAsCursor;
void
InitMembers();
// Check that the above condition holds.
#ifdef DEBUG
void AssertSourceIsCorrect() const;
#else
void AssertSourceIsCorrect() const {}
#endif
void
ConstructResult();
nsRefPtr<IDBTransaction> mTransaction;
JS::Heap<JS::Value> mResultVal;
nsRefPtr<mozilla::dom::DOMError> mError;
IndexedDBRequestParentBase* mActorParent;
nsString mFilename;
#ifdef MOZ_ENABLE_PROFILER_SPS
uint64_t mSerialNumber;
#endif
nsresult mErrorCode;
uint32_t mLineNo;
bool mHaveResultOrErrorCode;
void
CaptureCaller();
};
class IDBOpenDBRequest : public IDBRequest
class NS_NO_VTABLE IDBRequest::ResultCallback
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBOpenDBRequest, IDBRequest)
virtual nsresult
GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult) = 0;
static
already_AddRefed<IDBOpenDBRequest>
Create(IDBFactory* aFactory,
nsPIDOMWindow* aOwner,
JS::Handle<JSObject*> aScriptOwner);
protected:
ResultCallback()
{ }
};
void SetTransaction(IDBTransaction* aTransaction);
class IDBOpenDBRequest MOZ_FINAL
: public IDBRequest
{
// Only touched on the owning thread.
nsRefPtr<IDBFactory> mFactory;
public:
static already_AddRefed<IDBOpenDBRequest>
CreateForWindow(IDBFactory* aFactory,
nsPIDOMWindow* aOwner,
JS::Handle<JSObject*> aScriptOwner);
static already_AddRefed<IDBOpenDBRequest>
CreateForJS(IDBFactory* aFactory,
JS::Handle<JSObject*> aScriptOwner);
void
SetTransaction(IDBTransaction* aTransaction);
// nsIDOMEventTarget
virtual nsresult PostHandleEvent(
EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
virtual nsresult
PostHandleEvent(EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
DOMError* GetError(ErrorResult& aRv)
DOMError*
GetError(ErrorResult& aRv)
{
return IDBRequest::GetError(aRv);
}
@ -212,22 +240,24 @@ public:
return mFactory;
}
IMPL_EVENT_HANDLER(blocked);
IMPL_EVENT_HANDLER(upgradeneeded);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBOpenDBRequest, IDBRequest)
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
IMPL_EVENT_HANDLER(blocked);
IMPL_EVENT_HANDLER(upgradeneeded);
private:
IDBOpenDBRequest(IDBFactory* aFactory, nsPIDOMWindow* aOwner);
protected:
explicit IDBOpenDBRequest(nsPIDOMWindow* aOwner);
~IDBOpenDBRequest();
// Only touched on the main thread.
nsRefPtr<IDBFactory> mFactory;
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbrequest_h__

File diff suppressed because it is too large Load Diff

View File

@ -8,71 +8,48 @@
#define mozilla_dom_indexeddb_idbtransaction_h__
#include "mozilla/Attributes.h"
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "mozIStorageConnection.h"
#include "mozIStorageStatement.h"
#include "mozIStorageFunction.h"
#include "mozilla/dom/DOMError.h"
#include "nsIRunnable.h"
#include "nsAutoPtr.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "nsInterfaceHashtable.h"
#include "nsRefPtrHashtable.h"
#include "mozilla/dom/IDBTransactionBinding.h"
#include "mozilla/dom/indexedDB/IDBDatabase.h"
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
#include "mozilla/dom/indexedDB/FileInfo.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIRunnable.h"
#include "nsString.h"
#include "nsTArray.h"
class nsIThread;
class nsIDOMBlob;
class nsPIDOMWindow;
namespace mozilla {
class ErrorResult;
class EventChainPreVisitor;
} // namespace mozilla
BEGIN_INDEXEDDB_NAMESPACE
namespace dom {
class AsyncConnectionHelper;
class CommitHelper;
class DOMError;
class DOMStringList;
class PBlobChild;
namespace indexedDB {
class BackgroundCursorChild;
class BackgroundRequestChild;
class BackgroundTransactionChild;
class BackgroundVersionChangeTransactionChild;
class IDBDatabase;
class IDBObjectStore;
class IDBRequest;
class IndexedDBDatabaseChild;
class IndexedDBTransactionChild;
class IndexedDBTransactionParent;
struct ObjectStoreInfo;
class TransactionThreadPool;
class UpdateRefcountFunction;
class IndexMetadata;
class ObjectStoreSpec;
class OpenCursorParams;
class PBackgroundIDBDatabaseFileChild;
class RequestParams;
class IDBTransactionListener
class IDBTransaction MOZ_FINAL
: public IDBWrapperCache
, public nsIRunnable
{
public:
NS_IMETHOD_(MozExternalRefCountType) AddRef() = 0;
NS_IMETHOD_(MozExternalRefCountType) Release() = 0;
// Called just before dispatching the final events on the transaction.
virtual nsresult NotifyTransactionPreComplete(IDBTransaction* aTransaction) = 0;
// Called just after dispatching the final events on the transaction.
virtual nsresult NotifyTransactionPostComplete(IDBTransaction* aTransaction) = 0;
};
class IDBTransaction : public IDBWrapperCache,
public nsIRunnable
{
friend class AsyncConnectionHelper;
friend class CommitHelper;
friend class IndexedDBDatabaseChild;
friend class ThreadObserver;
friend class TransactionThreadPool;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIRUNNABLE
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, IDBWrapperCache)
enum Mode
{
READ_ONLY = 0,
@ -91,156 +68,184 @@ public:
DONE
};
private:
nsRefPtr<IDBDatabase> mDatabase;
nsRefPtr<DOMError> mError;
nsTArray<nsString> mObjectStoreNames;
nsTArray<nsRefPtr<IDBObjectStore>> mObjectStores;
nsTArray<nsRefPtr<IDBObjectStore>> mDeletedObjectStores;
// Tagged with mMode. If mMode is VERSION_CHANGE then mBackgroundActor will be
// a BackgroundVersionChangeTransactionChild. Otherwise it will be a
// BackgroundTransactionChild.
union {
BackgroundTransactionChild* mNormalBackgroundActor;
BackgroundVersionChangeTransactionChild* mVersionChangeBackgroundActor;
} mBackgroundActor;
// Only used for VERSION_CHANGE transactions.
int64_t mNextObjectStoreId;
int64_t mNextIndexId;
#ifdef MOZ_ENABLE_PROFILER_SPS
uint64_t mSerialNumber;
#endif
nsresult mAbortCode;
uint32_t mPendingRequestCount;
ReadyState mReadyState;
Mode mMode;
bool mCreating;
bool mAbortedByScript;
#ifdef DEBUG
bool mSentCommitOrAbort;
bool mFiredCompleteOrAbort;
#endif
public:
static already_AddRefed<IDBTransaction>
CreateVersionChange(IDBDatabase* aDatabase,
BackgroundVersionChangeTransactionChild* aActor,
int64_t aNextObjectStoreId,
int64_t aNextIndexId);
static already_AddRefed<IDBTransaction>
Create(IDBDatabase* aDatabase,
const Sequence<nsString>& aObjectStoreNames,
Mode aMode,
bool aDispatchDelayed)
const nsTArray<nsString>& aObjectStoreNames,
Mode aMode);
static IDBTransaction*
GetCurrent();
void
AssertIsOnOwningThread() const
#ifdef DEBUG
;
#else
{ }
#endif
void
SetBackgroundActor(BackgroundTransactionChild* aBackgroundActor);
void
ClearBackgroundActor()
{
return CreateInternal(aDatabase, aObjectStoreNames, aMode, aDispatchDelayed,
false);
AssertIsOnOwningThread();
if (mMode == VERSION_CHANGE) {
mBackgroundActor.mVersionChangeBackgroundActor = nullptr;
} else {
mBackgroundActor.mNormalBackgroundActor = nullptr;
}
}
// nsIDOMEventTarget
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
void
StartRequest(BackgroundRequestChild* aBackgroundActor,
const RequestParams& aParams);
void OnNewRequest();
void OnRequestFinished();
void OnRequestDisconnected();
void
OpenCursor(BackgroundCursorChild* aBackgroundActor,
const OpenCursorParams& aParams);
void RemoveObjectStore(const nsAString& aName);
void
RefreshSpec(bool aMayDelete);
void SetTransactionListener(IDBTransactionListener* aListener);
void
OnNewRequest();
bool StartSavepoint();
nsresult ReleaseSavepoint();
void RollbackSavepoint();
void
OnRequestFinished();
// Only meant to be called on mStorageThread!
nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
bool
IsOpen() const;
already_AddRefed<mozIStorageStatement>
GetCachedStatement(const nsACString& aQuery);
template<int N>
already_AddRefed<mozIStorageStatement>
GetCachedStatement(const char (&aQuery)[N])
{
return GetCachedStatement(NS_LITERAL_CSTRING(aQuery));
}
bool IsOpen() const;
bool IsFinished() const
bool
IsFinished() const
{
AssertIsOnOwningThread();
return mReadyState > LOADING;
}
bool IsWriteAllowed() const
bool
IsWriteAllowed() const
{
AssertIsOnOwningThread();
return mMode == READ_WRITE || mMode == VERSION_CHANGE;
}
bool IsAborted() const
bool
IsAborted() const
{
AssertIsOnOwningThread();
return NS_FAILED(mAbortCode);
}
// 'Get' prefix is to avoid name collisions with the enum
Mode GetMode()
Mode
GetMode() const
{
AssertIsOnOwningThread();
return mMode;
}
IDBDatabase* Database()
IDBDatabase*
Database() const
{
NS_ASSERTION(mDatabase, "This should never be null!");
AssertIsOnOwningThread();
return mDatabase;
}
DatabaseInfo* DBInfo() const
{
return mDatabaseInfo;
}
already_AddRefed<IDBObjectStore>
GetOrCreateObjectStore(const nsAString& aName,
ObjectStoreInfo* aObjectStoreInfo,
bool aCreating);
already_AddRefed<FileInfo> GetFileInfo(nsIDOMBlob* aBlob);
void AddFileInfo(nsIDOMBlob* aBlob, FileInfo* aFileInfo);
void ClearCreatedFileInfos();
void
SetActor(IndexedDBTransactionChild* aActorChild)
{
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
mActorChild = aActorChild;
}
void
SetActor(IndexedDBTransactionParent* aActorParent)
{
NS_ASSERTION(!aActorParent || !mActorParent,
"Shouldn't have more than one!");
mActorParent = aActorParent;
}
IndexedDBTransactionChild*
GetActorChild() const
{
return mActorChild;
}
IndexedDBTransactionParent*
GetActorParent() const
{
return mActorParent;
}
nsresult
Abort(IDBRequest* aRequest);
nsresult
Abort(nsresult aAbortCode);
nsresult
GetAbortCode() const
{
return mAbortCode;
}
#ifdef MOZ_ENABLE_PROFILER_SPS
uint64_t
GetSerialNumber() const
{
return mSerialNumber;
}
#endif
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
nsPIDOMWindow*
GetParentObject() const
{
return GetOwner();
}
IDBTransactionMode
GetMode(ErrorResult& aRv) const;
IDBDatabase*
Db() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return mDatabase;
return Database();
}
const nsTArray<nsString>&
ObjectStoreNamesInternal() const
{
AssertIsOnOwningThread();
return mObjectStoreNames;
}
already_AddRefed<IDBObjectStore>
CreateObjectStore(const ObjectStoreSpec& aSpec);
void
DeleteObjectStore(int64_t aObjectStoreId);
void
CreateIndex(IDBObjectStore* aObjectStore, const IndexMetadata& aMetadata);
void
DeleteIndex(IDBObjectStore* aObjectStore, int64_t aIndexId);
void
Abort(IDBRequest* aRequest);
void
Abort(nsresult aAbortCode);
#ifdef MOZ_ENABLE_PROFILER_SPS
uint32_t
GetSerialNumber() const
{
AssertIsOnOwningThread();
return mSerialNumber;
}
#endif
nsPIDOMWindow*
GetParentObject() const;
IDBTransactionMode
GetMode(ErrorResult& aRv) const;
DOMError*
GetError() const;
@ -248,255 +253,56 @@ public:
ObjectStore(const nsAString& aName, ErrorResult& aRv);
void
Abort(ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
aRv = AbortInternal(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR, nullptr);
}
Abort(ErrorResult& aRv);
IMPL_EVENT_HANDLER(abort)
IMPL_EVENT_HANDLER(complete)
IMPL_EVENT_HANDLER(error)
already_AddRefed<DOMStringList>
GetObjectStoreNames(ErrorResult& aRv);
ObjectStoreNames();
void
FireCompleteOrAbortEvents(nsresult aResult);
// Only for VERSION_CHANGE transactions.
int64_t
NextObjectStoreId();
// Only for VERSION_CHANGE transactions.
int64_t
NextIndexId();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIRUNNABLE
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, IDBWrapperCache)
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// nsIDOMEventTarget
virtual nsresult
PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
private:
nsresult
AbortInternal(nsresult aAbortCode,
already_AddRefed<mozilla::dom::DOMError> aError);
// Should only be called directly through IndexedDBDatabaseChild.
static already_AddRefed<IDBTransaction>
CreateInternal(IDBDatabase* aDatabase,
const Sequence<nsString>& aObjectStoreNames,
Mode aMode,
bool aDispatchDelayed,
bool aIsVersionChangeTransactionChild);
explicit IDBTransaction(IDBDatabase* aDatabase);
IDBTransaction(IDBDatabase* aDatabase,
const nsTArray<nsString>& aObjectStoreNames,
Mode aMode);
~IDBTransaction();
nsresult CommitOrRollback();
void
AbortInternal(nsresult aAbortCode, already_AddRefed<DOMError> aError);
nsRefPtr<IDBDatabase> mDatabase;
nsRefPtr<DatabaseInfo> mDatabaseInfo;
nsRefPtr<DOMError> mError;
nsTArray<nsString> mObjectStoreNames;
ReadyState mReadyState;
Mode mMode;
uint32_t mPendingRequests;
void
SendCommit();
nsInterfaceHashtable<nsCStringHashKey, mozIStorageStatement>
mCachedStatements;
nsRefPtr<IDBTransactionListener> mListener;
// Only touched on the database thread.
nsCOMPtr<mozIStorageConnection> mConnection;
// Only touched on the database thread.
uint32_t mSavepointCount;
nsTArray<nsRefPtr<IDBObjectStore> > mCreatedObjectStores;
nsTArray<nsRefPtr<IDBObjectStore> > mDeletedObjectStores;
nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
nsRefPtrHashtable<nsISupportsHashKey, FileInfo> mCreatedFileInfos;
IndexedDBTransactionChild* mActorChild;
IndexedDBTransactionParent* mActorParent;
nsresult mAbortCode;
#ifdef MOZ_ENABLE_PROFILER_SPS
uint64_t mSerialNumber;
#endif
bool mCreating;
#ifdef DEBUG
bool mFiredCompleteOrAbort;
#endif
void
SendAbort(nsresult aResultCode);
};
class CommitHelper MOZ_FINAL : public nsIRunnable
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
CommitHelper(IDBTransaction* aTransaction,
IDBTransactionListener* aListener,
const nsTArray<nsRefPtr<IDBObjectStore> >& mUpdatedObjectStores);
CommitHelper(IDBTransaction* aTransaction,
nsresult aAbortCode);
template<class T>
bool AddDoomedObject(nsCOMPtr<T>& aCOMPtr)
{
if (aCOMPtr) {
if (!mDoomedObjects.AppendElement(do_QueryInterface(aCOMPtr))) {
NS_ERROR("Out of memory!");
return false;
}
aCOMPtr = nullptr;
}
return true;
}
private:
~CommitHelper();
// Writes new autoincrement counts to database
nsresult WriteAutoIncrementCounts();
// Updates counts after a successful commit
void CommitAutoIncrementCounts();
// Reverts counts when a transaction is aborted
void RevertAutoIncrementCounts();
nsRefPtr<IDBTransaction> mTransaction;
nsRefPtr<IDBTransactionListener> mListener;
nsCOMPtr<mozIStorageConnection> mConnection;
nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
nsAutoTArray<nsCOMPtr<nsISupports>, 10> mDoomedObjects;
nsAutoTArray<nsRefPtr<IDBObjectStore>, 10> mAutoIncrementObjectStores;
nsresult mAbortCode;
};
class UpdateRefcountFunction MOZ_FINAL : public mozIStorageFunction
{
~UpdateRefcountFunction()
{ }
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_MOZISTORAGEFUNCTION
explicit UpdateRefcountFunction(FileManager* aFileManager)
: mFileManager(aFileManager), mInSavepoint(false)
{ }
void StartSavepoint()
{
MOZ_ASSERT(!mInSavepoint);
MOZ_ASSERT(!mSavepointEntriesIndex.Count());
mInSavepoint = true;
}
void ReleaseSavepoint()
{
MOZ_ASSERT(mInSavepoint);
mSavepointEntriesIndex.Clear();
mInSavepoint = false;
}
void RollbackSavepoint()
{
MOZ_ASSERT(mInSavepoint);
mInSavepoint = false;
mSavepointEntriesIndex.EnumerateRead(RollbackSavepointCallback, nullptr);
mSavepointEntriesIndex.Clear();
}
void ClearFileInfoEntries()
{
mFileInfoEntries.Clear();
}
nsresult WillCommit(mozIStorageConnection* aConnection);
void DidCommit();
void DidAbort();
private:
class FileInfoEntry
{
public:
explicit FileInfoEntry(FileInfo* aFileInfo)
: mFileInfo(aFileInfo), mDelta(0), mSavepointDelta(0)
{ }
~FileInfoEntry()
{ }
nsRefPtr<FileInfo> mFileInfo;
int32_t mDelta;
int32_t mSavepointDelta;
};
enum UpdateType {
eIncrement,
eDecrement
};
class DatabaseUpdateFunction
{
public:
DatabaseUpdateFunction(mozIStorageConnection* aConnection,
UpdateRefcountFunction* aFunction)
: mConnection(aConnection), mFunction(aFunction), mErrorCode(NS_OK)
{ }
bool Update(int64_t aId, int32_t aDelta);
nsresult ErrorCode()
{
return mErrorCode;
}
private:
nsresult UpdateInternal(int64_t aId, int32_t aDelta);
nsCOMPtr<mozIStorageConnection> mConnection;
nsCOMPtr<mozIStorageStatement> mUpdateStatement;
nsCOMPtr<mozIStorageStatement> mSelectStatement;
nsCOMPtr<mozIStorageStatement> mInsertStatement;
UpdateRefcountFunction* mFunction;
nsresult mErrorCode;
};
nsresult ProcessValue(mozIStorageValueArray* aValues,
int32_t aIndex,
UpdateType aUpdateType);
nsresult CreateJournals();
nsresult RemoveJournals(const nsTArray<int64_t>& aJournals);
static PLDHashOperator
DatabaseUpdateCallback(const uint64_t& aKey,
FileInfoEntry* aValue,
void* aUserArg);
static PLDHashOperator
FileInfoUpdateCallback(const uint64_t& aKey,
FileInfoEntry* aValue,
void* aUserArg);
static PLDHashOperator
RollbackSavepointCallback(const uint64_t& aKey,
FileInfoEntry* aValue,
void* aUserArg);
FileManager* mFileManager;
nsClassHashtable<nsUint64HashKey, FileInfoEntry> mFileInfoEntries;
nsDataHashtable<nsUint64HashKey, FileInfoEntry*> mSavepointEntriesIndex;
nsTArray<int64_t> mJournalsToCreateBeforeCommit;
nsTArray<int64_t> mJournalsToRemoveAfterCommit;
nsTArray<int64_t> mJournalsToRemoveAfterAbort;
bool mInSavepoint;
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbtransaction_h__

View File

@ -5,9 +5,19 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "IDBWrapperCache.h"
#include "nsCycleCollector.h"
USING_INDEXEDDB_NAMESPACE
#include "mozilla/HoldDropJSObjects.h"
#include "nsCOMPtr.h"
#include "nsIScriptGlobalObject.h"
#include "nsPIDOMWindow.h"
#ifdef DEBUG
#include "nsCycleCollector.h"
#endif
namespace mozilla {
namespace dom {
namespace indexedDB {
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBWrapperCache)
@ -38,6 +48,14 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(IDBWrapperCache, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(IDBWrapperCache, DOMEventTargetHelper)
IDBWrapperCache::IDBWrapperCache(DOMEventTargetHelper* aOwner)
: DOMEventTargetHelper(aOwner), mScriptOwner(nullptr)
{ }
IDBWrapperCache::IDBWrapperCache(nsPIDOMWindow* aOwner)
: DOMEventTargetHelper(aOwner), mScriptOwner(nullptr)
{ }
IDBWrapperCache::~IDBWrapperCache()
{
mScriptOwner = nullptr;
@ -48,7 +66,7 @@ IDBWrapperCache::~IDBWrapperCache()
void
IDBWrapperCache::SetScriptOwner(JSObject* aScriptOwner)
{
NS_ASSERTION(aScriptOwner, "This should never be null!");
MOZ_ASSERT(aScriptOwner);
mScriptOwner = aScriptOwner;
mozilla::HoldJSObjects(this);
@ -62,3 +80,7 @@ IDBWrapperCache::AssertIsRooted() const
"Why aren't we rooted?!");
}
#endif
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -7,47 +7,51 @@
#ifndef mozilla_dom_indexeddb_idbwrappercache_h__
#define mozilla_dom_indexeddb_idbwrappercache_h__
#include "js/RootingAPI.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
BEGIN_INDEXEDDB_NAMESPACE
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
namespace indexedDB {
class IDBWrapperCache : public DOMEventTargetHelper
{
JS::Heap<JSObject*> mScriptOwner;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
IDBWrapperCache,
DOMEventTargetHelper)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBWrapperCache,
DOMEventTargetHelper)
JSObject* GetScriptOwner() const
JSObject*
GetScriptOwner() const
{
return mScriptOwner;
}
void SetScriptOwner(JSObject* aScriptOwner);
void
SetScriptOwner(JSObject* aScriptOwner);
void AssertIsRooted() const
#ifdef DEBUG
void AssertIsRooted() const;
;
#else
inline void AssertIsRooted() const
{
}
{ }
#endif
protected:
explicit IDBWrapperCache(DOMEventTargetHelper* aOwner)
: DOMEventTargetHelper(aOwner), mScriptOwner(nullptr)
{ }
explicit IDBWrapperCache(nsPIDOMWindow* aOwner)
: DOMEventTargetHelper(aOwner), mScriptOwner(nullptr)
{ }
explicit IDBWrapperCache(DOMEventTargetHelper* aOwner);
explicit IDBWrapperCache(nsPIDOMWindow* aOwner);
virtual ~IDBWrapperCache();
private:
JS::Heap<JSObject*> mScriptOwner;
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_idbwrappercache_h__

View File

@ -9,148 +9,70 @@
#include "nsIProgrammingLanguage.h"
#include "mozilla/Attributes.h"
#include "js/StructuredClone.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsIInputStream.h"
#define BEGIN_INDEXEDDB_NAMESPACE \
namespace mozilla { namespace dom { namespace indexedDB {
#define END_INDEXEDDB_NAMESPACE \
} /* namespace indexedDB */ } /* namepsace dom */ } /* namespace mozilla */
#define USING_INDEXEDDB_NAMESPACE \
using namespace mozilla::dom::indexedDB;
class nsIDOMBlob;
class nsIInputStream;
BEGIN_INDEXEDDB_NAMESPACE
namespace mozilla {
namespace dom {
namespace indexedDB {
class FileInfo;
class IDBDatabase;
class IDBTransaction;
class SerializedStructuredCloneReadInfo;
class SerializedStructuredCloneWriteInfo;
struct StructuredCloneFile
{
bool operator==(const StructuredCloneFile& aOther) const
{
return this->mFile == aOther.mFile &&
this->mFileInfo == aOther.mFileInfo &&
this->mInputStream == aOther.mInputStream;
}
nsCOMPtr<nsIDOMBlob> mFile;
nsRefPtr<FileInfo> mFileInfo;
nsCOMPtr<nsIInputStream> mInputStream;
};
struct SerializedStructuredCloneReadInfo;
// In IndexedDatabaseInlines.h
inline
StructuredCloneFile();
// In IndexedDatabaseInlines.h
inline
~StructuredCloneFile();
// In IndexedDatabaseInlines.h
inline bool
operator==(const StructuredCloneFile& aOther) const;
};
struct StructuredCloneReadInfo
{
// In IndexedDatabaseInlines.h
inline StructuredCloneReadInfo();
inline StructuredCloneReadInfo&
operator=(StructuredCloneReadInfo&& aCloneReadInfo);
// In IndexedDatabaseInlines.h
inline bool
SetFromSerialized(const SerializedStructuredCloneReadInfo& aOther);
JSAutoStructuredCloneBuffer mCloneBuffer;
nsTArray<uint8_t> mData;
nsTArray<StructuredCloneFile> mFiles;
IDBDatabase* mDatabase;
};
struct SerializedStructuredCloneReadInfo
{
SerializedStructuredCloneReadInfo()
: data(nullptr), dataLength(0)
{ }
bool
operator==(const SerializedStructuredCloneReadInfo& aOther) const
{
return this->data == aOther.data &&
this->dataLength == aOther.dataLength;
}
SerializedStructuredCloneReadInfo&
operator=(const StructuredCloneReadInfo& aOther)
{
data = aOther.mCloneBuffer.data();
dataLength = aOther.mCloneBuffer.nbytes();
return *this;
}
// Make sure to update ipc/SerializationHelpers.h when changing members here!
uint64_t* data;
size_t dataLength;
};
struct SerializedStructuredCloneWriteInfo;
struct StructuredCloneWriteInfo
{
// In IndexedDatabaseInlines.h
inline StructuredCloneWriteInfo();
inline StructuredCloneWriteInfo(StructuredCloneWriteInfo&& aCloneWriteInfo);
bool operator==(const StructuredCloneWriteInfo& aOther) const
{
return this->mCloneBuffer.nbytes() == aOther.mCloneBuffer.nbytes() &&
this->mCloneBuffer.data() == aOther.mCloneBuffer.data() &&
this->mFiles == aOther.mFiles &&
this->mTransaction == aOther.mTransaction &&
this->mOffsetToKeyProp == aOther.mOffsetToKeyProp;
}
// In IndexedDatabaseInlines.h
inline bool
SetFromSerialized(const SerializedStructuredCloneWriteInfo& aOther);
// XXX Remove!
JSAutoStructuredCloneBuffer mCloneBuffer;
nsTArray<StructuredCloneFile> mFiles;
IDBTransaction* mTransaction;
uint64_t mOffsetToKeyProp;
// In IndexedDatabaseInlines.h
inline
StructuredCloneReadInfo();
// In IndexedDatabaseInlines.h
inline
~StructuredCloneReadInfo();
// In IndexedDatabaseInlines.h
inline StructuredCloneReadInfo&
operator=(StructuredCloneReadInfo&& aOther);
// In IndexedDatabaseInlines.h
inline
StructuredCloneReadInfo(SerializedStructuredCloneReadInfo&& aOther);
};
struct SerializedStructuredCloneWriteInfo
{
SerializedStructuredCloneWriteInfo()
: data(nullptr), dataLength(0), offsetToKeyProp(0)
{ }
bool
operator==(const SerializedStructuredCloneWriteInfo& aOther) const
{
return this->data == aOther.data &&
this->dataLength == aOther.dataLength &&
this->offsetToKeyProp == aOther.offsetToKeyProp;
}
SerializedStructuredCloneWriteInfo&
operator=(const StructuredCloneWriteInfo& aOther)
{
data = aOther.mCloneBuffer.data();
dataLength = aOther.mCloneBuffer.nbytes();
offsetToKeyProp = aOther.mOffsetToKeyProp;
return *this;
}
// Make sure to update ipc/SerializationHelpers.h when changing members here!
uint64_t* data;
size_t dataLength;
uint64_t offsetToKeyProp;
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_indexeddb_indexeddatabase_h__

View File

@ -11,48 +11,55 @@
#error Must include IndexedDatabase.h first
#endif
BEGIN_INDEXEDDB_NAMESPACE
#include "FileInfo.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
#include "nsIDOMFile.h"
#include "nsIInputStream.h"
namespace mozilla {
namespace dom {
namespace indexedDB {
inline
StructuredCloneWriteInfo::StructuredCloneWriteInfo()
: mTransaction(nullptr),
mOffsetToKeyProp(0)
StructuredCloneFile::StructuredCloneFile()
{
MOZ_COUNT_CTOR(StructuredCloneFile);
}
inline
StructuredCloneWriteInfo::StructuredCloneWriteInfo(
StructuredCloneWriteInfo&& aCloneWriteInfo)
: mCloneBuffer(Move(aCloneWriteInfo.mCloneBuffer))
, mTransaction(aCloneWriteInfo.mTransaction)
, mOffsetToKeyProp(aCloneWriteInfo.mOffsetToKeyProp)
StructuredCloneFile::~StructuredCloneFile()
{
mFiles.SwapElements(aCloneWriteInfo.mFiles);
aCloneWriteInfo.mTransaction = nullptr;
aCloneWriteInfo.mOffsetToKeyProp = 0;
MOZ_COUNT_DTOR(StructuredCloneFile);
}
inline
bool
StructuredCloneWriteInfo::SetFromSerialized(
const SerializedStructuredCloneWriteInfo& aOther)
StructuredCloneFile::operator==(const StructuredCloneFile& aOther) const
{
if (!aOther.dataLength) {
mCloneBuffer.clear();
}
else if (!mCloneBuffer.copy(aOther.data, aOther.dataLength)) {
return false;
}
mFiles.Clear();
mOffsetToKeyProp = aOther.offsetToKeyProp;
return true;
return this->mFile == aOther.mFile &&
this->mFileInfo == aOther.mFileInfo;
}
inline
StructuredCloneReadInfo::StructuredCloneReadInfo()
: mDatabase(nullptr)
: mDatabase(nullptr)
{
MOZ_COUNT_CTOR(StructuredCloneReadInfo);
}
inline
StructuredCloneReadInfo::StructuredCloneReadInfo(
SerializedStructuredCloneReadInfo&& aCloneReadInfo)
: mData(Move(aCloneReadInfo.data()))
, mDatabase(nullptr)
{
MOZ_COUNT_CTOR(StructuredCloneReadInfo);
}
inline
StructuredCloneReadInfo::~StructuredCloneReadInfo()
{
MOZ_COUNT_DTOR(StructuredCloneReadInfo);
}
inline StructuredCloneReadInfo&
@ -60,6 +67,7 @@ StructuredCloneReadInfo::operator=(StructuredCloneReadInfo&& aCloneReadInfo)
{
MOZ_ASSERT(&aCloneReadInfo != this);
mData = Move(aCloneReadInfo.mData);
mCloneBuffer = Move(aCloneReadInfo.mCloneBuffer);
mFiles.Clear();
mFiles.SwapElements(aCloneReadInfo.mFiles);
@ -68,45 +76,8 @@ StructuredCloneReadInfo::operator=(StructuredCloneReadInfo&& aCloneReadInfo)
return *this;
}
inline
bool
StructuredCloneReadInfo::SetFromSerialized(
const SerializedStructuredCloneReadInfo& aOther)
{
if (aOther.dataLength &&
!mCloneBuffer.copy(aOther.data, aOther.dataLength)) {
return false;
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
mFiles.Clear();
return true;
}
inline
void
AppendConditionClause(const nsACString& aColumnName,
const nsACString& aArgName,
bool aLessThan,
bool aEquals,
nsACString& aResult)
{
aResult += NS_LITERAL_CSTRING(" AND ") + aColumnName +
NS_LITERAL_CSTRING(" ");
if (aLessThan) {
aResult.Append('<');
}
else {
aResult.Append('>');
}
if (aEquals) {
aResult.Append('=');
}
aResult += NS_LITERAL_CSTRING(" :") + aArgName;
}
END_INDEXEDDB_NAMESPACE
#endif
#endif // IndexedDatabaseInlines_h

View File

@ -16,12 +16,16 @@
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/CondVar.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ErrorEventBinding.h"
#include "mozilla/dom/PBlobChild.h"
#include "mozilla/dom/quota/OriginOrPatternString.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/Utilities.h"
#include "mozilla/dom/TabContext.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
#include "mozilla/storage.h"
@ -53,12 +57,11 @@
#define LOW_DISK_SPACE_DATA_FULL "full"
#define LOW_DISK_SPACE_DATA_FREE "free"
USING_INDEXEDDB_NAMESPACE
using namespace mozilla;
using namespace mozilla::dom;
USING_QUOTA_NAMESPACE
namespace mozilla {
namespace dom {
namespace indexedDB {
BEGIN_INDEXEDDB_NAMESPACE
using namespace mozilla::dom::quota;
class FileManagerInfo
{
@ -103,14 +106,15 @@ private:
nsTArray<nsRefPtr<FileManager> > mTemporaryStorageFileManagers;
};
END_INDEXEDDB_NAMESPACE
namespace {
const char kTestingPref[] = "dom.indexedDB.testing";
mozilla::StaticRefPtr<IndexedDatabaseManager> gDBManager;
mozilla::Atomic<bool> gInitialized(false);
mozilla::Atomic<bool> gClosed(false);
mozilla::Atomic<bool> gTestingMode(false);
class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable
{
@ -183,6 +187,16 @@ struct MOZ_STACK_CLASS InvalidateInfo
const nsACString& pattern;
};
void
TestingPrefChangedCallback(const char* aPrefName, void* aClosure)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!strcmp(aPrefName, kTestingPref));
MOZ_ASSERT(!aClosure);
gTestingMode = Preferences::GetBool(aPrefName);
}
} // anonymous namespace
IndexedDatabaseManager::IndexedDatabaseManager()
@ -281,6 +295,9 @@ IndexedDatabaseManager::Init()
NS_ENSURE_SUCCESS(rv, rv);
}
Preferences::RegisterCallbackAndCall(TestingPrefChangedCallback,
kTestingPref);
return NS_OK;
}
@ -293,6 +310,8 @@ IndexedDatabaseManager::Destroy()
NS_ERROR("Shutdown more than once?!");
}
Preferences::UnregisterCallback(TestingPrefChangedCallback, kTestingPref);
delete this;
}
@ -314,7 +333,7 @@ IndexedDatabaseManager::FireWindowOnError(nsPIDOMWindow* aOwner,
nsresult rv = aVisitor.mDOMEvent->GetType(type);
NS_ENSURE_SUCCESS(rv, rv);
if (!type.EqualsLiteral(ERROR_EVT_STR)) {
if (nsDependentString(kErrorEventType) != type) {
return NS_OK;
}
@ -425,8 +444,9 @@ IndexedDatabaseManager::DefineIndexedDB(JSContext* aCx,
}
nsRefPtr<IDBFactory> factory;
if (NS_FAILED(IDBFactory::Create(aCx, aGlobal, nullptr,
getter_AddRefs(factory)))) {
if (NS_FAILED(IDBFactory::CreateForChromeJS(aCx,
aGlobal,
getter_AddRefs(factory)))) {
return false;
}
@ -471,6 +491,16 @@ IndexedDatabaseManager::InLowDiskSpaceMode()
}
#endif
// static
bool
IndexedDatabaseManager::InTestingMode()
{
MOZ_ASSERT(gDBManager,
"InTestingMode() called before indexedDB has been initialized!");
return gTestingMode;
}
already_AddRefed<FileManager>
IndexedDatabaseManager::GetFileManager(PersistenceType aPersistenceType,
const nsACString& aOrigin,
@ -626,13 +656,38 @@ IndexedDatabaseManager::BlockAndGetFileReferences(
int32_t* aSliceRefCnt,
bool* aResult)
{
nsRefPtr<GetFileReferencesHelper> helper =
new GetFileReferencesHelper(aPersistenceType, aOrigin, aDatabaseName,
aFileId);
if (NS_WARN_IF(!InTestingMode())) {
return NS_ERROR_UNEXPECTED;
}
nsresult rv = helper->DispatchAndReturnFileReferences(aRefCnt, aDBRefCnt,
aSliceRefCnt, aResult);
NS_ENSURE_SUCCESS(rv, rv);
if (IsMainProcess()) {
nsRefPtr<GetFileReferencesHelper> helper =
new GetFileReferencesHelper(aPersistenceType, aOrigin, aDatabaseName,
aFileId);
nsresult rv =
helper->DispatchAndReturnFileReferences(aRefCnt, aDBRefCnt,
aSliceRefCnt, aResult);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
ContentChild* contentChild = ContentChild::GetSingleton();
if (NS_WARN_IF(!contentChild)) {
return NS_ERROR_FAILURE;
}
if (!contentChild->SendGetFileReferences(aPersistenceType,
nsCString(aOrigin),
nsString(aDatabaseName),
aFileId,
aRefCnt,
aDBRefCnt,
aSliceRefCnt,
aResult)) {
return NS_ERROR_FAILURE;
}
}
return NS_OK;
}
@ -886,3 +941,7 @@ GetFileReferencesHelper::Run()
return NS_OK;
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -7,8 +7,6 @@
#ifndef mozilla_dom_indexeddb_indexeddatabasemanager_h__
#define mozilla_dom_indexeddb_indexeddatabasemanager_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "nsIObserver.h"
#include "js/TypeDecls.h"
@ -21,16 +19,20 @@
class nsPIDOMWindow;
namespace mozilla {
class EventChainPostVisitor;
namespace dom {
class TabContext;
namespace quota {
class OriginOrPatternString;
}
}
}
BEGIN_INDEXEDDB_NAMESPACE
class EventChainPostVisitor;
namespace dom {
class TabContext;
namespace quota {
class OriginOrPatternString;
} // namespace quota
namespace indexedDB {
class FileManager;
class FileManagerInfo;
@ -75,6 +77,9 @@ public:
}
#endif
static bool
InTestingMode();
already_AddRefed<FileManager>
GetFileManager(PersistenceType aPersistenceType,
const nsACString& aOrigin,
@ -160,6 +165,8 @@ private:
static mozilla::Atomic<bool> sLowDiskSpaceMode;
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_indexeddb_indexeddatabasemanager_h__ */
#endif // mozilla_dom_indexeddb_indexeddatabasemanager_h__

View File

@ -4,19 +4,23 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/FloatingPoint.h"
#include "Key.h"
#include "ReportInternalError.h"
#include <algorithm>
#include "js/Value.h"
#include "jsfriendapi.h"
#include "mozilla/Endian.h"
#include "mozilla/FloatingPoint.h"
#include "mozIStorageStatement.h"
#include "nsAlgorithm.h"
#include "nsJSUtils.h"
#include "ReportInternalError.h"
#include "xpcpublic.h"
#include "mozilla/Endian.h"
#include <algorithm>
USING_INDEXEDDB_NAMESPACE
namespace mozilla {
namespace dom {
namespace indexedDB {
/*
Here's how we encode keys:
@ -262,6 +266,14 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
#define TWO_BYTE_ADJUST (-0x7F)
#define THREE_BYTE_SHIFT 6
nsresult
Key::EncodeJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
uint8_t aTypeOffset)
{
return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
}
void
Key::EncodeString(const nsAString& aString, uint8_t aTypeOffset)
{
@ -314,6 +326,17 @@ Key::EncodeString(const nsAString& aString, uint8_t aTypeOffset)
NS_ASSERTION(buffer == mBuffer.EndReading(), "Wrote wrong number of bytes");
}
// static
nsresult
Key::DecodeJSVal(const unsigned char*& aPos,
const unsigned char* aEnd,
JSContext* aCx,
uint8_t aTypeOffset,
JS::MutableHandle<JS::Value> aVal)
{
return DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, aVal, 0);
}
// static
void
Key::DecodeString(const unsigned char*& aPos, const unsigned char* aEnd,
@ -428,3 +451,108 @@ Key::DecodeNumber(const unsigned char*& aPos, const unsigned char* aEnd)
return pun.d;
}
nsresult
Key::BindToStatement(mozIStorageStatement* aStatement,
const nsACString& aParamName) const
{
nsresult rv = aStatement->BindBlobByName(aParamName,
reinterpret_cast<const uint8_t*>(mBuffer.get()), mBuffer.Length());
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
nsresult
Key::SetFromStatement(mozIStorageStatement* aStatement,
uint32_t aIndex)
{
uint8_t* data;
uint32_t dataLength = 0;
nsresult rv = aStatement->GetBlob(aIndex, &dataLength, &data);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
mBuffer.Adopt(
reinterpret_cast<char*>(const_cast<uint8_t*>(data)), dataLength);
return NS_OK;
}
nsresult
Key::SetFromJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal)
{
mBuffer.Truncate();
if (aVal.isNull() || aVal.isUndefined()) {
Unset();
return NS_OK;
}
nsresult rv = EncodeJSVal(aCx, aVal, 0);
if (NS_FAILED(rv)) {
Unset();
return rv;
}
TrimBuffer();
return NS_OK;
}
nsresult
Key::ToJSVal(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal) const
{
if (IsUnset()) {
aVal.setUndefined();
return NS_OK;
}
const unsigned char* pos = BufferStart();
nsresult rv = DecodeJSVal(pos, BufferEnd(), aCx, 0, aVal);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(pos >= BufferEnd());
return NS_OK;
}
nsresult
Key::ToJSVal(JSContext* aCx,
JS::Heap<JS::Value>& aVal) const
{
JS::Rooted<JS::Value> value(aCx);
nsresult rv = ToJSVal(aCx, &value);
if (NS_SUCCEEDED(rv)) {
aVal = value;
}
return rv;
}
nsresult
Key::AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal)
{
nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
if (NS_FAILED(rv)) {
Unset();
return rv;
}
return NS_OK;
}
#ifdef DEBUG
void
Key::Assert(bool aCondition) const
{
MOZ_ASSERT(aCondition);
}
#endif // DEBUG
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -7,84 +7,91 @@
#ifndef mozilla_dom_indexeddb_key_h__
#define mozilla_dom_indexeddb_key_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "js/RootingAPI.h"
#include "nsString.h"
#include "mozIStorageStatement.h"
#include "js/Value.h"
class mozIStorageStatement;
namespace IPC {
template <typename T> struct ParamTraits;
template <typename> struct ParamTraits;
} // namespace IPC
BEGIN_INDEXEDDB_NAMESPACE
namespace mozilla {
namespace dom {
namespace indexedDB {
class Key
{
friend struct IPC::ParamTraits<Key>;
nsCString mBuffer;
public:
Key()
{
Unset();
}
Key& operator=(const nsAString& aString)
Key&
operator=(const nsAString& aString)
{
SetFromString(aString);
return *this;
}
Key& operator=(int64_t aInt)
Key&
operator=(int64_t aInt)
{
SetFromInteger(aInt);
return *this;
}
bool operator==(const Key& aOther) const
bool
operator==(const Key& aOther) const
{
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
"Don't compare unset keys!");
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
return mBuffer.Equals(aOther.mBuffer);
}
bool operator!=(const Key& aOther) const
bool
operator!=(const Key& aOther) const
{
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
"Don't compare unset keys!");
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
return !mBuffer.Equals(aOther.mBuffer);
}
bool operator<(const Key& aOther) const
bool
operator<(const Key& aOther) const
{
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
"Don't compare unset keys!");
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
return Compare(mBuffer, aOther.mBuffer) < 0;
}
bool operator>(const Key& aOther) const
bool
operator>(const Key& aOther) const
{
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
"Don't compare unset keys!");
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
return Compare(mBuffer, aOther.mBuffer) > 0;
}
bool operator<=(const Key& aOther) const
bool
operator<=(const Key& aOther) const
{
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
"Don't compare unset keys!");
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
return Compare(mBuffer, aOther.mBuffer) <= 0;
}
bool operator>=(const Key& aOther) const
bool
operator>=(const Key& aOther) const
{
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
"Don't compare unset keys!");
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
return Compare(mBuffer, aOther.mBuffer) >= 0;
}
@ -95,169 +102,114 @@ public:
mBuffer.SetIsVoid(true);
}
bool IsUnset() const
bool
IsUnset() const
{
return mBuffer.IsVoid();
}
bool IsFloat() const
bool
IsFloat() const
{
return !IsUnset() && mBuffer.First() == eFloat;
}
bool IsDate() const
bool
IsDate() const
{
return !IsUnset() && mBuffer.First() == eDate;
}
bool IsString() const
bool
IsString() const
{
return !IsUnset() && mBuffer.First() == eString;
}
bool IsArray() const
bool
IsArray() const
{
return !IsUnset() && mBuffer.First() >= eArray;
}
double ToFloat() const
double
ToFloat() const
{
NS_ASSERTION(IsFloat(), "Why'd you call this?");
Assert(IsFloat());
const unsigned char* pos = BufferStart();
double res = DecodeNumber(pos, BufferEnd());
NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
Assert(pos >= BufferEnd());
return res;
}
double ToDateMsec() const
double
ToDateMsec() const
{
NS_ASSERTION(IsDate(), "Why'd you call this?");
Assert(IsDate());
const unsigned char* pos = BufferStart();
double res = DecodeNumber(pos, BufferEnd());
NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
Assert(pos >= BufferEnd());
return res;
}
void ToString(nsString& aString) const
void
ToString(nsString& aString) const
{
NS_ASSERTION(IsString(), "Why'd you call this?");
Assert(IsString());
const unsigned char* pos = BufferStart();
DecodeString(pos, BufferEnd(), aString);
NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
Assert(pos >= BufferEnd());
}
void SetFromString(const nsAString& aString)
void
SetFromString(const nsAString& aString)
{
mBuffer.Truncate();
EncodeString(aString, 0);
TrimBuffer();
}
void SetFromInteger(int64_t aInt)
void
SetFromInteger(int64_t aInt)
{
mBuffer.Truncate();
EncodeNumber(double(aInt), eFloat);
TrimBuffer();
}
nsresult SetFromJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal)
{
mBuffer.Truncate();
nsresult
SetFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal);
if (aVal.isNull() || aVal.isUndefined()) {
Unset();
return NS_OK;
}
nsresult
ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) const;
nsresult rv = EncodeJSVal(aCx, aVal, 0);
if (NS_FAILED(rv)) {
Unset();
return rv;
}
TrimBuffer();
nsresult
ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aVal) const;
return NS_OK;
}
nsresult
AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal);
nsresult ToJSVal(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal) const
{
if (IsUnset()) {
aVal.setUndefined();
return NS_OK;
}
const unsigned char* pos = BufferStart();
nsresult rv = DecodeJSVal(pos, BufferEnd(), aCx, 0, aVal);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(pos >= BufferEnd(),
"Didn't consume whole buffer");
return NS_OK;
}
nsresult ToJSVal(JSContext* aCx,
JS::Heap<JS::Value>& aVal) const
{
JS::Rooted<JS::Value> value(aCx);
nsresult rv = ToJSVal(aCx, &value);
if (NS_SUCCEEDED(rv)) {
aVal = value;
}
return rv;
}
nsresult AppendItem(JSContext* aCx,
bool aFirstOfArray,
JS::Handle<JS::Value> aVal)
{
nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
if (NS_FAILED(rv)) {
Unset();
return rv;
}
return NS_OK;
}
void FinishArray()
void
FinishArray()
{
TrimBuffer();
}
const nsCString& GetBuffer() const
const nsCString&
GetBuffer() const
{
return mBuffer;
}
nsresult BindToStatement(mozIStorageStatement* aStatement,
const nsACString& aParamName) const
{
nsresult rv = aStatement->BindBlobByName(aParamName,
reinterpret_cast<const uint8_t*>(mBuffer.get()), mBuffer.Length());
nsresult
BindToStatement(mozIStorageStatement* aStatement,
const nsACString& aParamName) const;
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
nsresult
SetFromStatement(mozIStorageStatement* aStatement, uint32_t aIndex);
nsresult SetFromStatement(mozIStorageStatement* aStatement,
uint32_t aIndex)
{
uint8_t* data;
uint32_t dataLength = 0;
nsresult rv = aStatement->GetBlob(aIndex, &dataLength, &data);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
mBuffer.Adopt(
reinterpret_cast<char*>(const_cast<uint8_t*>(data)), dataLength);
return NS_OK;
}
static
int16_t CompareKeys(Key& aFirst, Key& aSecond)
static int16_t
CompareKeys(Key& aFirst, Key& aSecond)
{
int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer);
@ -273,12 +225,14 @@ public:
}
private:
const unsigned char* BufferStart() const
const unsigned char*
BufferStart() const
{
return reinterpret_cast<const unsigned char*>(mBuffer.BeginReading());
}
const unsigned char* BufferEnd() const
const unsigned char*
BufferEnd() const
{
return reinterpret_cast<const unsigned char*>(mBuffer.EndReading());
}
@ -294,7 +248,8 @@ private:
// Encoding helper. Trims trailing zeros off of mBuffer as a post-processing
// step.
void TrimBuffer()
void
TrimBuffer()
{
const char* end = mBuffer.EndReading() - 1;
while (!*end) {
@ -305,41 +260,57 @@ private:
}
// Encoding functions. These append the encoded value to the end of mBuffer
inline nsresult EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal,
uint8_t aTypeOffset)
{
return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
}
void EncodeString(const nsAString& aString, uint8_t aTypeOffset);
void EncodeNumber(double aFloat, uint8_t aType);
nsresult
EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, uint8_t aTypeOffset);
void
EncodeString(const nsAString& aString, uint8_t aTypeOffset);
void
EncodeNumber(double aFloat, uint8_t aType);
// Decoding functions. aPos points into mBuffer and is adjusted to point
// past the consumed value.
static inline nsresult DecodeJSVal(const unsigned char*& aPos,
const unsigned char* aEnd, JSContext* aCx,
uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal)
{
return DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, aVal, 0);
}
static nsresult
DecodeJSVal(const unsigned char*& aPos,
const unsigned char* aEnd,
JSContext* aCx,
uint8_t aTypeOffset,
JS::MutableHandle<JS::Value> aVal);
static void DecodeString(const unsigned char*& aPos,
const unsigned char* aEnd,
nsString& aString);
static double DecodeNumber(const unsigned char*& aPos,
const unsigned char* aEnd);
static void
DecodeString(const unsigned char*& aPos,
const unsigned char* aEnd,
nsString& aString);
nsCString mBuffer;
static double
DecodeNumber(const unsigned char*& aPos, const unsigned char* aEnd);
private:
nsresult EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
uint8_t aTypeOffset, uint16_t aRecursionDepth);
nsresult
EncodeJSValInternal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
uint8_t aTypeOffset,
uint16_t aRecursionDepth);
static nsresult DecodeJSValInternal(const unsigned char*& aPos,
const unsigned char* aEnd,
JSContext* aCx, uint8_t aTypeOffset,
JS::MutableHandle<JS::Value> aVal, uint16_t aRecursionDepth);
static nsresult
DecodeJSValInternal(const unsigned char*& aPos,
const unsigned char* aEnd,
JSContext* aCx,
uint8_t aTypeOffset,
JS::MutableHandle<JS::Value> aVal,
uint16_t aRecursionDepth);
void
Assert(bool aCondition) const
#ifdef DEBUG
;
#else
{ }
#endif
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_indexeddb_key_h__ */
#endif // mozilla_dom_indexeddb_key_h__

View File

@ -15,7 +15,9 @@
#include "mozilla/dom/BindingDeclarations.h"
USING_INDEXEDDB_NAMESPACE
namespace mozilla {
namespace dom {
namespace indexedDB {
namespace {
@ -178,8 +180,9 @@ GetJSValFromKeyPathString(JSContext* aCx,
obj = dummy;
}
else {
JS::Rooted<JSObject*> dummy(aCx, JS_NewObject(aCx, &IDBObjectStore::sDummyPropJSClass,
JS::NullPtr(), JS::NullPtr()));
JS::Rooted<JSObject*> dummy(aCx,
JS_NewObject(aCx, IDBObjectStore::DummyPropClass(), JS::NullPtr(),
JS::NullPtr()));
if (!dummy) {
IDB_REPORT_INTERNAL_ERR();
rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@ -569,3 +572,7 @@ KeyPath::IsAllowedForObjectStore(bool aAutoIncrement) const
// Everything else is ok.
return true;
}
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -7,16 +7,28 @@
#ifndef mozilla_dom_indexeddb_keypath_h__
#define mozilla_dom_indexeddb_keypath_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "mozilla/dom/BindingDeclarations.h"
BEGIN_INDEXEDDB_NAMESPACE
namespace mozilla {
namespace dom {
namespace indexedDB {
class IndexMetadata;
class Key;
class ObjectStoreMetadata;
class KeyPath
{
// This private constructor is only to be used by IPDL-generated classes.
friend class IndexMetadata;
friend class ObjectStoreMetadata;
KeyPath()
: mType(NONEXISTENT)
{
MOZ_COUNT_CTOR(KeyPath);
}
public:
enum KeyPathType {
NONEXISTENT,
@ -105,6 +117,8 @@ public:
nsTArray<nsString> mStrings;
};
END_INDEXEDDB_NAMESPACE
} // namespace indexedDB
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_indexeddb_keypath_h__ */
#endif // mozilla_dom_indexeddb_keypath_h__

File diff suppressed because it is too large Load Diff

View File

@ -1,175 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_indexeddb_opendatabasehelper_h__
#define mozilla_dom_indexeddb_opendatabasehelper_h__
#include "AsyncConnectionHelper.h"
#include "nsIRunnable.h"
#include "mozilla/dom/quota/StoragePrivilege.h"
#include "DatabaseInfo.h"
#include "IDBDatabase.h"
#include "IDBRequest.h"
class mozIStorageConnection;
namespace mozilla {
namespace dom {
class nsIContentParent;
}
}
BEGIN_INDEXEDDB_NAMESPACE
class CheckPermissionsHelper;
class OpenDatabaseHelper : public HelperBase
{
friend class CheckPermissionsHelper;
typedef mozilla::dom::quota::PersistenceType PersistenceType;
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
~OpenDatabaseHelper() {}
public:
OpenDatabaseHelper(IDBOpenDBRequest* aRequest,
const nsAString& aName,
const nsACString& aGroup,
const nsACString& aASCIIOrigin,
uint64_t aRequestedVersion,
PersistenceType aPersistenceType,
bool aForDeletion,
mozilla::dom::nsIContentParent* aContentParent,
StoragePrivilege aPrivilege)
: HelperBase(aRequest), mOpenDBRequest(aRequest), mName(aName),
mGroup(aGroup), mASCIIOrigin(aASCIIOrigin),
mRequestedVersion(aRequestedVersion), mPersistenceType(aPersistenceType),
mForDeletion(aForDeletion), mPrivilege(aPrivilege),
mContentParent(aContentParent), mCurrentVersion(0), mLastObjectStoreId(0),
mLastIndexId(0), mState(eCreated), mResultCode(NS_OK),
mLoadDBMetadata(false),
mTrackingQuota(aPrivilege != mozilla::dom::quota::Chrome)
{
NS_ASSERTION(!aForDeletion || !aRequestedVersion,
"Can't be for deletion and request a version!");
}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
nsresult Init();
nsresult WaitForOpenAllowed();
nsresult Dispatch(nsIEventTarget* aDatabaseThread);
nsresult DispatchToIOThread();
nsresult RunImmediately();
void SetError(nsresult rv)
{
NS_ASSERTION(NS_FAILED(rv), "Why are you telling me?");
mResultCode = rv;
}
virtual nsresult GetResultCode() MOZ_OVERRIDE
{
return mResultCode;
}
nsresult NotifySetVersionFinished();
nsresult NotifyDeleteFinished();
void BlockDatabase();
const nsACString& Id() const
{
return mDatabaseId;
}
IDBDatabase* Database() const
{
NS_ASSERTION(mDatabase, "Calling at the wrong time!");
return mDatabase;
}
const StoragePrivilege& Privilege() const
{
return mPrivilege;
}
static
nsresult CreateDatabaseConnection(nsIFile* aDBFile,
nsIFile* aFMDirectory,
const nsAString& aName,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
mozIStorageConnection** aConnection);
protected:
// Methods only called on the main thread
nsresult EnsureSuccessResult();
nsresult StartSetVersion();
nsresult StartDelete();
virtual nsresult GetSuccessResult(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
void DispatchSuccessEvent();
void DispatchErrorEvent();
virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
// Called by CheckPermissionsHelper on the main thread before dispatch.
void SetUnlimitedQuotaAllowed()
{
mTrackingQuota = false;
}
// Methods only called on the DB thread
nsresult DoDatabaseWork();
// In-params.
nsRefPtr<IDBOpenDBRequest> mOpenDBRequest;
nsString mName;
nsCString mGroup;
nsCString mASCIIOrigin;
uint64_t mRequestedVersion;
PersistenceType mPersistenceType;
bool mForDeletion;
StoragePrivilege mPrivilege;
nsCString mDatabaseId;
mozilla::dom::nsIContentParent* mContentParent;
// Out-params.
nsTArray<nsRefPtr<ObjectStoreInfo> > mObjectStores;
uint64_t mCurrentVersion;
nsString mDatabaseFilePath;
int64_t mLastObjectStoreId;
int64_t mLastIndexId;
nsRefPtr<IDBDatabase> mDatabase;
// State variables
enum OpenDatabaseState {
eCreated = 0, // Not yet dispatched to the DB thread
eOpenPending, // Waiting for open allowed/open allowed
eDBWork, // Waiting to do/doing work on the DB thread
eFiringEvents, // Waiting to fire/firing events on the main thread
eSetVersionPending, // Waiting on a SetVersionHelper
eSetVersionCompleted, // SetVersionHelper is done
eDeletePending, // Waiting on a DeleteDatabaseHelper
eDeleteCompleted, // DeleteDatabaseHelper is done
};
OpenDatabaseState mState;
nsresult mResultCode;
nsRefPtr<FileManager> mFileManager;
nsRefPtr<DatabaseInfo> mDBInfo;
bool mLoadDBMetadata;
bool mTrackingQuota;
};
END_INDEXEDDB_NAMESPACE
#endif // mozilla_dom_indexeddb_opendatabasehelper_h__

View File

@ -0,0 +1,90 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackgroundIDBTransaction;
include protocol PBackgroundIDBVersionChangeTransaction;
include protocol PBlob;
include PBackgroundIDBSharedTypes;
include "mozilla/dom/indexedDB/SerializationHelpers.h";
using struct mozilla::void_t
from "ipc/IPCMessageUtils.h";
using class mozilla::dom::indexedDB::Key
from "mozilla/dom/indexedDB/Key.h";
namespace mozilla {
namespace dom {
namespace indexedDB {
struct ContinueParams
{
Key key;
};
struct AdvanceParams
{
uint32_t count;
};
union CursorRequestParams
{
ContinueParams;
AdvanceParams;
};
struct ObjectStoreCursorResponse
{
Key key;
SerializedStructuredCloneReadInfo cloneInfo;
};
struct ObjectStoreKeyCursorResponse
{
Key key;
};
struct IndexCursorResponse
{
Key key;
Key objectKey;
SerializedStructuredCloneReadInfo cloneInfo;
};
struct IndexKeyCursorResponse
{
Key key;
Key objectKey;
};
union CursorResponse
{
void_t;
nsresult;
ObjectStoreCursorResponse;
ObjectStoreKeyCursorResponse;
IndexCursorResponse;
IndexKeyCursorResponse;
};
protocol PBackgroundIDBCursor
{
manager PBackgroundIDBTransaction or PBackgroundIDBVersionChangeTransaction;
parent:
DeleteMe();
Continue(CursorRequestParams params);
child:
__delete__();
Response(CursorResponse response);
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,72 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackgroundIDBDatabaseFile;
include protocol PBackgroundIDBFactory;
include protocol PBackgroundIDBTransaction;
include protocol PBackgroundIDBVersionChangeTransaction;
include protocol PBlob;
include InputStreamParams;
include PBackgroundIDBSharedTypes;
include "mozilla/dom/indexedDB/SerializationHelpers.h";
using struct mozilla::null_t
from "ipc/IPCMessageUtils.h";
using mozilla::dom::indexedDB::IDBTransaction::Mode
from "mozilla/dom/indexedDB/IDBTransaction.h";
namespace mozilla {
namespace dom {
namespace indexedDB {
union NullableVersion
{
null_t;
uint64_t;
};
union BlobOrInputStream
{
PBlob;
InputStreamParams;
};
protocol PBackgroundIDBDatabase
{
manager PBackgroundIDBFactory;
manages PBackgroundIDBDatabaseFile;
manages PBackgroundIDBTransaction;
manages PBackgroundIDBVersionChangeTransaction;
parent:
DeleteMe();
Blocked();
Close();
PBackgroundIDBDatabaseFile(BlobOrInputStream blobOrInputStream);
PBackgroundIDBTransaction(nsString[] objectStoreNames, Mode mode);
child:
__delete__();
VersionChange(uint64_t oldVersion, NullableVersion newVersion);
Invalidate();
PBackgroundIDBVersionChangeTransaction(uint64_t currentVersion,
uint64_t requestedVersion,
int64_t nextObjectStoreId,
int64_t nextIndexId);
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -2,20 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PIndexedDB;
include protocol PBackgroundIDBDatabase;
namespace mozilla {
namespace dom {
namespace indexedDB {
protocol PIndexedDBDeleteDatabaseRequest
protocol PBackgroundIDBDatabaseFile
{
manager PIndexedDB;
manager PBackgroundIDBDatabase;
child:
__delete__(nsresult rv);
Blocked(uint64_t currentVersion);
parent:
__delete__();
};
} // namespace indexedDB

View File

@ -0,0 +1,63 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PBackgroundIDBDatabase;
include protocol PBackgroundIDBFactoryRequest;
include PBackgroundIDBSharedTypes;
include PBackgroundSharedTypes;
using struct mozilla::void_t
from "ipc/IPCMessageUtils.h";
namespace mozilla {
namespace dom {
namespace indexedDB {
struct CommonFactoryRequestParams
{
DatabaseMetadata metadata;
PrincipalInfo principalInfo;
bool privateBrowsingMode;
};
struct OpenDatabaseRequestParams
{
CommonFactoryRequestParams commonParams;
};
struct DeleteDatabaseRequestParams
{
CommonFactoryRequestParams commonParams;
};
union FactoryRequestParams
{
OpenDatabaseRequestParams;
DeleteDatabaseRequestParams;
};
protocol PBackgroundIDBFactory
{
manager PBackground;
manages PBackgroundIDBDatabase;
manages PBackgroundIDBFactoryRequest;
parent:
DeleteMe();
PBackgroundIDBFactoryRequest(FactoryRequestParams params);
child:
__delete__();
PBackgroundIDBDatabase(DatabaseSpec spec,
PBackgroundIDBFactoryRequest request);
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,48 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackgroundIDBFactory;
include protocol PBackgroundIDBDatabase;
include PBackgroundSharedTypes;
namespace mozilla {
namespace dom {
namespace indexedDB {
struct OpenDatabaseRequestResponse
{
PBackgroundIDBDatabase database;
};
struct DeleteDatabaseRequestResponse
{
uint64_t previousVersion;
};
union FactoryRequestResponse
{
nsresult;
OpenDatabaseRequestResponse;
DeleteDatabaseRequestResponse;
};
protocol PBackgroundIDBFactoryRequest
{
manager PBackgroundIDBFactory;
child:
__delete__(FactoryRequestResponse response);
PermissionChallenge(PrincipalInfo principalInfo);
Blocked(uint64_t currentVersion);
parent:
PermissionRetry();
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,112 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackgroundIDBTransaction;
include protocol PBackgroundIDBVersionChangeTransaction;
include protocol PBlob;
include PBackgroundIDBSharedTypes;
include "mozilla/dom/indexedDB/SerializationHelpers.h";
using struct mozilla::void_t
from "ipc/IPCMessageUtils.h";
using class mozilla::dom::indexedDB::Key
from "mozilla/dom/indexedDB/Key.h";
namespace mozilla {
namespace dom {
namespace indexedDB {
struct ObjectStoreAddResponse
{
Key key;
};
struct ObjectStorePutResponse
{
Key key;
};
struct ObjectStoreGetResponse
{
SerializedStructuredCloneReadInfo cloneInfo;
};
struct ObjectStoreGetAllResponse
{
SerializedStructuredCloneReadInfo[] cloneInfos;
};
struct ObjectStoreGetAllKeysResponse
{
Key[] keys;
};
struct ObjectStoreDeleteResponse
{ };
struct ObjectStoreClearResponse
{ };
struct ObjectStoreCountResponse
{
uint64_t count;
};
struct IndexGetResponse
{
SerializedStructuredCloneReadInfo cloneInfo;
};
struct IndexGetKeyResponse
{
Key key;
};
struct IndexGetAllResponse
{
SerializedStructuredCloneReadInfo[] cloneInfos;
};
struct IndexGetAllKeysResponse
{
Key[] keys;
};
struct IndexCountResponse
{
uint64_t count;
};
union RequestResponse
{
nsresult;
ObjectStoreGetResponse;
ObjectStoreAddResponse;
ObjectStorePutResponse;
ObjectStoreDeleteResponse;
ObjectStoreClearResponse;
ObjectStoreCountResponse;
ObjectStoreGetAllResponse;
ObjectStoreGetAllKeysResponse;
IndexGetResponse;
IndexGetKeyResponse;
IndexGetAllResponse;
IndexGetAllKeysResponse;
IndexCountResponse;
};
protocol PBackgroundIDBRequest
{
manager PBackgroundIDBTransaction or PBackgroundIDBVersionChangeTransaction;
child:
__delete__(RequestResponse response);
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,259 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBlob;
include protocol PBackgroundIDBDatabaseFile;
include "mozilla/dom/indexedDB/SerializationHelpers.h";
using struct mozilla::void_t
from "ipc/IPCMessageUtils.h";
using mozilla::dom::indexedDB::IDBCursor::Direction
from "mozilla/dom/indexedDB/IDBCursor.h";
using class mozilla::dom::indexedDB::Key
from "mozilla/dom/indexedDB/Key.h";
using class mozilla::dom::indexedDB::KeyPath
from "mozilla/dom/indexedDB/KeyPath.h";
using mozilla::dom::quota::PersistenceType
from "mozilla/dom/quota/PersistenceType.h";
namespace mozilla {
namespace dom {
namespace indexedDB {
struct SerializedKeyRange
{
Key lower;
Key upper;
bool lowerOpen;
bool upperOpen;
bool isOnly;
};
struct SerializedStructuredCloneReadInfo
{
uint8_t[] data;
PBlob[] blobs;
// This will only be valid for parent process actors.
intptr_t[] fileInfos;
};
struct SerializedStructuredCloneWriteInfo
{
uint8_t[] data;
uint64_t offsetToKeyProp;
};
struct IndexUpdateInfo
{
int64_t indexId;
Key value;
};
union OptionalKeyRange
{
SerializedKeyRange;
void_t;
};
struct DatabaseMetadata
{
nsString name;
uint64_t version;
PersistenceType persistenceType;
bool persistenceTypeIsExplicit;
};
struct ObjectStoreMetadata
{
int64_t id;
nsString name;
KeyPath keyPath;
bool autoIncrement;
};
struct IndexMetadata
{
int64_t id;
nsString name;
KeyPath keyPath;
bool unique;
bool multiEntry;
};
struct DatabaseSpec
{
DatabaseMetadata metadata;
ObjectStoreSpec[] objectStores;
};
struct ObjectStoreSpec
{
ObjectStoreMetadata metadata;
IndexMetadata[] indexes;
};
struct ObjectStoreOpenCursorParams
{
int64_t objectStoreId;
OptionalKeyRange optionalKeyRange;
Direction direction;
};
struct ObjectStoreOpenKeyCursorParams
{
int64_t objectStoreId;
OptionalKeyRange optionalKeyRange;
Direction direction;
};
struct IndexOpenCursorParams
{
int64_t objectStoreId;
int64_t indexId;
OptionalKeyRange optionalKeyRange;
Direction direction;
};
struct IndexOpenKeyCursorParams
{
int64_t objectStoreId;
int64_t indexId;
OptionalKeyRange optionalKeyRange;
Direction direction;
};
union OpenCursorParams
{
ObjectStoreOpenCursorParams;
ObjectStoreOpenKeyCursorParams;
IndexOpenCursorParams;
IndexOpenKeyCursorParams;
};
// XXX Remove this once MutableFile has been ported to PBackground.
union DatabaseFileOrMutableFileId
{
PBackgroundIDBDatabaseFile;
int64_t;
};
struct ObjectStoreAddPutParams
{
int64_t objectStoreId;
SerializedStructuredCloneWriteInfo cloneInfo;
Key key;
IndexUpdateInfo[] indexUpdateInfos;
DatabaseFileOrMutableFileId[] files;
};
struct ObjectStoreAddParams
{
ObjectStoreAddPutParams commonParams;
};
struct ObjectStorePutParams
{
ObjectStoreAddPutParams commonParams;
};
struct ObjectStoreGetParams
{
int64_t objectStoreId;
SerializedKeyRange keyRange;
};
struct ObjectStoreGetAllParams
{
int64_t objectStoreId;
OptionalKeyRange optionalKeyRange;
uint32_t limit;
};
struct ObjectStoreGetAllKeysParams
{
int64_t objectStoreId;
OptionalKeyRange optionalKeyRange;
uint32_t limit;
};
struct ObjectStoreDeleteParams
{
int64_t objectStoreId;
SerializedKeyRange keyRange;
};
struct ObjectStoreClearParams
{
int64_t objectStoreId;
};
struct ObjectStoreCountParams
{
int64_t objectStoreId;
OptionalKeyRange optionalKeyRange;
};
struct IndexGetParams
{
int64_t objectStoreId;
int64_t indexId;
SerializedKeyRange keyRange;
};
struct IndexGetKeyParams
{
int64_t objectStoreId;
int64_t indexId;
SerializedKeyRange keyRange;
};
struct IndexGetAllParams
{
int64_t objectStoreId;
int64_t indexId;
OptionalKeyRange optionalKeyRange;
uint32_t limit;
};
struct IndexGetAllKeysParams
{
int64_t objectStoreId;
int64_t indexId;
OptionalKeyRange optionalKeyRange;
uint32_t limit;
};
struct IndexCountParams
{
int64_t objectStoreId;
int64_t indexId;
OptionalKeyRange optionalKeyRange;
};
union RequestParams
{
ObjectStoreAddParams;
ObjectStorePutParams;
ObjectStoreGetParams;
ObjectStoreGetAllParams;
ObjectStoreGetAllKeysParams;
ObjectStoreDeleteParams;
ObjectStoreClearParams;
ObjectStoreCountParams;
IndexGetParams;
IndexGetKeyParams;
IndexGetAllParams;
IndexGetAllKeysParams;
IndexCountParams;
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,41 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackgroundIDBCursor;
include protocol PBackgroundIDBDatabase;
include protocol PBackgroundIDBDatabaseFile;
include protocol PBackgroundIDBRequest;
include PBackgroundIDBSharedTypes;
namespace mozilla {
namespace dom {
namespace indexedDB {
protocol PBackgroundIDBTransaction
{
manager PBackgroundIDBDatabase;
manages PBackgroundIDBCursor;
manages PBackgroundIDBRequest;
parent:
DeleteMe();
Commit();
Abort(nsresult resultCode);
PBackgroundIDBCursor(OpenCursorParams params);
PBackgroundIDBRequest(RequestParams params);
child:
__delete__();
Complete(nsresult result);
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,49 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackgroundIDBCursor;
include protocol PBackgroundIDBDatabase;
include protocol PBackgroundIDBRequest;
include protocol PBlob;
include PBackgroundIDBSharedTypes;
namespace mozilla {
namespace dom {
namespace indexedDB {
protocol PBackgroundIDBVersionChangeTransaction
{
manager PBackgroundIDBDatabase;
manages PBackgroundIDBCursor;
manages PBackgroundIDBRequest;
parent:
DeleteMe();
Commit();
Abort(nsresult resultCode);
CreateObjectStore(ObjectStoreMetadata metadata);
DeleteObjectStore(int64_t objectStoreId);
CreateIndex(int64_t objectStoreId,
IndexMetadata metadata);
DeleteIndex(int64_t objectStoreId,
int64_t indexId);
PBackgroundIDBCursor(OpenCursorParams params);
PBackgroundIDBRequest(RequestParams params);
child:
__delete__();
Complete(nsresult result);
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,27 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBrowser;
namespace mozilla {
namespace dom {
namespace indexedDB {
protocol PIndexedDBPermissionRequest
{
manager PBrowser;
child:
/**
* Called when the user makes a choice or the permission request times out.
*
* @param permission
* The permission result (see nsIPermissionManager.idl for valid values).
*/
__delete__(uint32_t permission);
};
} // namespace indexedDB
} // namespace dom
} // namespace mozilla

Some files were not shown because too many files have changed in this diff Show More