mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1286798 - Part 29: Implement implicit snapshotting of databases; r=asuth,mccr8
This improves performance a lot in cases when multiple operations are invoked by a single JS function (number of sync IPC calls is reduced to a minimum). It also improves correctness since changes are not visible to other content processes until a JS function finishes. The patch implements core infrastructure, all items are sent to content when a snapshot is initialized and everything is fully working. However, sending of all items at once is not optimal for bigger databases. Support for lazy loading of items is implemented in a following patch.
This commit is contained in:
parent
54be9b7307
commit
c4f55013cf
@ -10,6 +10,7 @@
|
||||
#include "LSDatabase.h"
|
||||
#include "LSObject.h"
|
||||
#include "LSObserver.h"
|
||||
#include "LSSnapshot.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -66,7 +67,7 @@ LSDatabaseChild::RecvRequestAllowToClose()
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mDatabase) {
|
||||
mDatabase->AllowToClose();
|
||||
mDatabase->RequestAllowToClose();
|
||||
|
||||
// TODO: A new datastore will be prepared at first LocalStorage API
|
||||
// synchronous call. It would be better to start preparing a new
|
||||
@ -77,6 +78,24 @@ LSDatabaseChild::RecvRequestAllowToClose()
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
PBackgroundLSSnapshotChild*
|
||||
LSDatabaseChild::AllocPBackgroundLSSnapshotChild(const nsString& aDocumentURI,
|
||||
const int64_t& aRequestedSize,
|
||||
LSSnapshotInitInfo* aInitInfo)
|
||||
{
|
||||
MOZ_CRASH("PBackgroundLSSnapshotChild actor should be manually constructed!");
|
||||
}
|
||||
|
||||
bool
|
||||
LSDatabaseChild::DeallocPBackgroundLSSnapshotChild(
|
||||
PBackgroundLSSnapshotChild* aActor)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* LSObserverChild
|
||||
******************************************************************************/
|
||||
@ -251,5 +270,51 @@ LSSimpleRequestChild::Recv__delete__(const LSSimpleRequestResponse& aResponse)
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* LSSnapshotChild
|
||||
******************************************************************************/
|
||||
|
||||
LSSnapshotChild::LSSnapshotChild(LSSnapshot* aSnapshot)
|
||||
: mSnapshot(aSnapshot)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aSnapshot);
|
||||
|
||||
MOZ_COUNT_CTOR(LSSnapshotChild);
|
||||
}
|
||||
|
||||
LSSnapshotChild::~LSSnapshotChild()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
MOZ_COUNT_DTOR(LSSnapshotChild);
|
||||
}
|
||||
|
||||
void
|
||||
LSSnapshotChild::SendDeleteMeInternal()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mSnapshot) {
|
||||
mSnapshot->ClearActor();
|
||||
mSnapshot = nullptr;
|
||||
|
||||
MOZ_ALWAYS_TRUE(PBackgroundLSSnapshotChild::SendDeleteMe());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LSSnapshotChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mSnapshot) {
|
||||
mSnapshot->ClearActor();
|
||||
#ifdef DEBUG
|
||||
mSnapshot = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/PBackgroundLSObserverChild.h"
|
||||
#include "mozilla/dom/PBackgroundLSRequestChild.h"
|
||||
#include "mozilla/dom/PBackgroundLSSimpleRequestChild.h"
|
||||
#include "mozilla/dom/PBackgroundLSSnapshotChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -28,6 +29,7 @@ class LSObject;
|
||||
class LSObserver;
|
||||
class LSRequestChildCallback;
|
||||
class LSSimpleRequestChildCallback;
|
||||
class LSSnapshot;
|
||||
|
||||
class LSDatabaseChild final
|
||||
: public PBackgroundLSDatabaseChild
|
||||
@ -63,6 +65,15 @@ private:
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvRequestAllowToClose() override;
|
||||
|
||||
PBackgroundLSSnapshotChild*
|
||||
AllocPBackgroundLSSnapshotChild(const nsString& aDocumentURI,
|
||||
const int64_t& aRequestedSize,
|
||||
LSSnapshotInitInfo* aInitInfo) override;
|
||||
|
||||
bool
|
||||
DeallocPBackgroundLSSnapshotChild(PBackgroundLSSnapshotChild* aActor)
|
||||
override;
|
||||
};
|
||||
|
||||
class LSObserverChild final
|
||||
@ -203,6 +214,38 @@ protected:
|
||||
{ }
|
||||
};
|
||||
|
||||
class LSSnapshotChild final
|
||||
: public PBackgroundLSSnapshotChild
|
||||
{
|
||||
friend class LSDatabase;
|
||||
friend class LSSnapshot;
|
||||
|
||||
LSSnapshot* mSnapshot;
|
||||
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
public:
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(LSSnapshotChild);
|
||||
}
|
||||
|
||||
private:
|
||||
// Only created by LSDatabase.
|
||||
explicit LSSnapshotChild(LSSnapshot* aSnapshot);
|
||||
|
||||
// Only destroyed by LSDatabaseChild.
|
||||
~LSSnapshotChild();
|
||||
|
||||
void
|
||||
SendDeleteMeInternal();
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,8 +19,10 @@ StaticAutoPtr<LSDatabaseHashtable> gLSDatabases;
|
||||
|
||||
LSDatabase::LSDatabase(const nsACString& aOrigin)
|
||||
: mActor(nullptr)
|
||||
, mSnapshot(nullptr)
|
||||
, mOrigin(aOrigin)
|
||||
, mAllowedToClose(false)
|
||||
, mRequestedAllowToClose(false)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
@ -35,6 +37,7 @@ LSDatabase::LSDatabase(const nsACString& aOrigin)
|
||||
LSDatabase::~LSDatabase()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(!mSnapshot);
|
||||
|
||||
if (!mAllowedToClose) {
|
||||
AllowToClose();
|
||||
@ -63,11 +66,239 @@ LSDatabase::SetActor(LSDatabaseChild* aActor)
|
||||
mActor = aActor;
|
||||
}
|
||||
|
||||
void
|
||||
LSDatabase::RequestAllowToClose()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(!mRequestedAllowToClose);
|
||||
|
||||
mRequestedAllowToClose = true;
|
||||
|
||||
if (!mSnapshot) {
|
||||
AllowToClose();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LSDatabase::NoteFinishedSnapshot(LSSnapshot* aSnapshot)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aSnapshot == mSnapshot);
|
||||
|
||||
mSnapshot = nullptr;
|
||||
|
||||
if (mRequestedAllowToClose) {
|
||||
AllowToClose();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::GetLength(LSObject* aObject,
|
||||
uint32_t* aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aObject);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mSnapshot->GetLength(aResult);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::GetKey(LSObject* aObject,
|
||||
uint32_t aIndex,
|
||||
nsAString& aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aObject);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mSnapshot->GetKey(aIndex, aResult);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::GetItem(LSObject* aObject,
|
||||
const nsAString& aKey,
|
||||
nsAString& aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aObject);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mSnapshot->GetItem(aKey, aResult);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::GetKeys(LSObject* aObject,
|
||||
nsTArray<nsString>& aKeys)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aObject);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mSnapshot->GetKeys(aKeys);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::SetItem(LSObject* aObject,
|
||||
const nsAString& aKey,
|
||||
const nsAString& aValue,
|
||||
LSNotifyInfo& aNotifyInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aObject);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mSnapshot->SetItem(aKey, aValue, aNotifyInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::RemoveItem(LSObject* aObject,
|
||||
const nsAString& aKey,
|
||||
LSNotifyInfo& aNotifyInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aObject);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mSnapshot->RemoveItem(aKey, aNotifyInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::Clear(LSObject* aObject,
|
||||
LSNotifyInfo& aNotifyInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aObject);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mSnapshot->Clear(aNotifyInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::EnsureSnapshot(LSObject* aObject,
|
||||
bool aRequestedBySetItem)
|
||||
{
|
||||
MOZ_ASSERT(aObject);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
if (mSnapshot) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<LSSnapshot> snapshot = new LSSnapshot(this);
|
||||
|
||||
LSSnapshotChild* actor = new LSSnapshotChild(snapshot);
|
||||
|
||||
int64_t requestedSize = aRequestedBySetItem ? 4096 : 0;
|
||||
|
||||
LSSnapshotInitInfo initInfo;
|
||||
bool ok =
|
||||
mActor->SendPBackgroundLSSnapshotConstructor(actor,
|
||||
aObject->DocumentURI(),
|
||||
requestedSize,
|
||||
&initInfo);
|
||||
if (NS_WARN_IF(!ok)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
snapshot->SetActor(actor);
|
||||
|
||||
// This add refs snapshot.
|
||||
nsresult rv = snapshot->Init(initInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// This is cleared in LSSnapshot::Run() before the snapshot is destroyed.
|
||||
mSnapshot = snapshot;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
LSDatabase::AllowToClose()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
MOZ_ASSERT(!mSnapshot);
|
||||
|
||||
mAllowedToClose = true;
|
||||
|
||||
@ -84,130 +315,5 @@ LSDatabase::AllowToClose()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::GetLength(uint32_t* aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
uint32_t result;
|
||||
if (NS_WARN_IF(!mActor->SendGetLength(&result))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aResult = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::GetKey(uint32_t aIndex,
|
||||
nsAString& aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsString result;
|
||||
if (NS_WARN_IF(!mActor->SendGetKey(aIndex, &result))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aResult = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::GetItem(const nsAString& aKey,
|
||||
nsAString& aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsString result;
|
||||
if (NS_WARN_IF(!mActor->SendGetItem(nsString(aKey), &result))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aResult = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::GetKeys(nsTArray<nsString>& aKeys)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
nsTArray<nsString> result;
|
||||
if (NS_WARN_IF(!mActor->SendGetKeys(&result))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aKeys.SwapElements(result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::SetItem(const nsAString& aDocumentURI,
|
||||
const nsAString& aKey,
|
||||
const nsAString& aValue,
|
||||
LSWriteOpResponse& aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
LSWriteOpResponse response;
|
||||
if (NS_WARN_IF(!mActor->SendSetItem(nsString(aDocumentURI),
|
||||
nsString(aKey),
|
||||
nsString(aValue),
|
||||
&response))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aResponse = response;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::RemoveItem(const nsAString& aDocumentURI,
|
||||
const nsAString& aKey,
|
||||
LSWriteOpResponse& aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
LSWriteOpResponse response;
|
||||
if (NS_WARN_IF(!mActor->SendRemoveItem(nsString(aDocumentURI),
|
||||
nsString(aKey),
|
||||
&response))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aResponse = response;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSDatabase::Clear(const nsAString& aDocumentURI,
|
||||
LSWriteOpResponse& aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mAllowedToClose);
|
||||
|
||||
LSWriteOpResponse response;
|
||||
if (NS_WARN_IF(!mActor->SendClear(nsString(aDocumentURI), &response))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aResponse = response;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -11,15 +11,18 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class LSDatabaseChild;
|
||||
class LSWriteOpResponse;
|
||||
class LSSnapshot;
|
||||
|
||||
class LSDatabase final
|
||||
{
|
||||
LSDatabaseChild* mActor;
|
||||
|
||||
LSSnapshot* mSnapshot;
|
||||
|
||||
const nsCString mOrigin;
|
||||
|
||||
bool mAllowedToClose;
|
||||
bool mRequestedAllowToClose;
|
||||
|
||||
public:
|
||||
explicit LSDatabase(const nsACString& aOrigin);
|
||||
@ -47,9 +50,6 @@ public:
|
||||
mActor = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
AllowToClose();
|
||||
|
||||
bool
|
||||
IsAllowedToClose() const
|
||||
{
|
||||
@ -58,37 +58,54 @@ public:
|
||||
return mAllowedToClose;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetLength(uint32_t* aResult);
|
||||
void
|
||||
RequestAllowToClose();
|
||||
|
||||
void
|
||||
NoteFinishedSnapshot(LSSnapshot* aSnapshot);
|
||||
|
||||
nsresult
|
||||
GetKey(uint32_t aIndex,
|
||||
GetLength(LSObject* aObject,
|
||||
uint32_t* aResult);
|
||||
|
||||
nsresult
|
||||
GetKey(LSObject* aObject,
|
||||
uint32_t aIndex,
|
||||
nsAString& aResult);
|
||||
|
||||
nsresult
|
||||
GetItem(const nsAString& aKey,
|
||||
GetItem(LSObject* aObject,
|
||||
const nsAString& aKey,
|
||||
nsAString& aResult);
|
||||
|
||||
nsresult
|
||||
GetKeys(nsTArray<nsString>& aKeys);
|
||||
GetKeys(LSObject* aObject,
|
||||
nsTArray<nsString>& aKeys);
|
||||
|
||||
nsresult
|
||||
SetItem(const nsAString& aDocumentURI,
|
||||
SetItem(LSObject* aObject,
|
||||
const nsAString& aKey,
|
||||
const nsAString& aValue,
|
||||
LSWriteOpResponse& aResponse);
|
||||
LSNotifyInfo& aNotifyInfo);
|
||||
|
||||
nsresult
|
||||
RemoveItem(const nsAString& aDocumentURI,
|
||||
RemoveItem(LSObject* aObject,
|
||||
const nsAString& aKey,
|
||||
LSWriteOpResponse& aResponse);
|
||||
LSNotifyInfo& aNotifyInfo);
|
||||
|
||||
nsresult
|
||||
Clear(const nsAString& aDocumentURI,
|
||||
LSWriteOpResponse& aResponse);
|
||||
Clear(LSObject* aObject,
|
||||
LSNotifyInfo& aNotifyInfo);
|
||||
|
||||
private:
|
||||
~LSDatabase();
|
||||
|
||||
nsresult
|
||||
EnsureSnapshot(LSObject* aObject,
|
||||
bool aRequestedBySetItem);
|
||||
|
||||
void
|
||||
AllowToClose();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -349,7 +349,7 @@ LSObject::GetLength(nsIPrincipal& aSubjectPrincipal,
|
||||
}
|
||||
|
||||
uint32_t result;
|
||||
rv = mDatabase->GetLength(&result);
|
||||
rv = mDatabase->GetLength(this, &result);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return 0;
|
||||
@ -378,7 +378,7 @@ LSObject::Key(uint32_t aIndex,
|
||||
}
|
||||
|
||||
nsString result;
|
||||
rv = mDatabase->GetKey(aIndex, result);
|
||||
rv = mDatabase->GetKey(this, aIndex, result);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return;
|
||||
@ -407,7 +407,7 @@ LSObject::GetItem(const nsAString& aKey,
|
||||
}
|
||||
|
||||
nsString result;
|
||||
rv = mDatabase->GetItem(aKey, result);
|
||||
rv = mDatabase->GetItem(this, aKey, result);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return;
|
||||
@ -432,7 +432,7 @@ LSObject::GetSupportedNames(nsTArray<nsString>& aNames)
|
||||
return;
|
||||
}
|
||||
|
||||
rv = mDatabase->GetKeys(aNames);
|
||||
rv = mDatabase->GetKeys(this, aNames);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
@ -457,16 +457,12 @@ LSObject::SetItem(const nsAString& aKey,
|
||||
return;
|
||||
}
|
||||
|
||||
LSWriteOpResponse response;
|
||||
rv = mDatabase->SetItem(mDocumentURI, aKey, aValue, response);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
LSNotifyInfo info;
|
||||
rv = GetInfoFromResponse(response, info);
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = mDatabase->SetItem(this, aKey, aValue, info);
|
||||
if (rv == NS_ERROR_FILE_NO_DEVICE_SPACE) {
|
||||
rv = NS_ERROR_DOM_QUOTA_EXCEEDED_ERR;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return;
|
||||
}
|
||||
@ -494,16 +490,9 @@ LSObject::RemoveItem(const nsAString& aKey,
|
||||
return;
|
||||
}
|
||||
|
||||
LSWriteOpResponse response;
|
||||
rv = mDatabase->RemoveItem(mDocumentURI, aKey, response);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
LSNotifyInfo info;
|
||||
rv = GetInfoFromResponse(response, info);
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = mDatabase->RemoveItem(this, aKey, info);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return;
|
||||
}
|
||||
@ -530,16 +519,9 @@ LSObject::Clear(nsIPrincipal& aSubjectPrincipal,
|
||||
return;
|
||||
}
|
||||
|
||||
LSWriteOpResponse response;
|
||||
rv = mDatabase->Clear(mDocumentURI, response);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
LSNotifyInfo info;
|
||||
rv = GetInfoFromResponse(response, info);
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = mDatabase->Clear(this, info);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return;
|
||||
}
|
||||
@ -780,28 +762,6 @@ LSObject::DropObserver()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSObject::GetInfoFromResponse(const LSWriteOpResponse& aResponse,
|
||||
LSNotifyInfo& aInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (aResponse.type() == LSWriteOpResponse::Tnsresult) {
|
||||
nsresult errorCode = aResponse.get_nsresult();
|
||||
|
||||
if (errorCode == NS_ERROR_FILE_NO_DEVICE_SPACE) {
|
||||
errorCode = NS_ERROR_DOM_QUOTA_EXCEEDED_ERR;
|
||||
}
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aResponse.type() == LSWriteOpResponse::TLSNotifyInfo);
|
||||
|
||||
aInfo = aResponse.get_LSNotifyInfo();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
LSObject::OnChange(const nsAString& aKey,
|
||||
const nsAString& aOldValue,
|
||||
|
@ -26,14 +26,12 @@ class PrincipalInfo;
|
||||
namespace dom {
|
||||
|
||||
class LSDatabase;
|
||||
class LSNotifyInfo;
|
||||
class LSObjectChild;
|
||||
class LSObserver;
|
||||
class LSRequestChild;
|
||||
class LSRequestChildCallback;
|
||||
class LSRequestParams;
|
||||
class LSRequestResponse;
|
||||
class LSWriteOpResponse;
|
||||
|
||||
class LSObject final
|
||||
: public Storage
|
||||
@ -80,6 +78,12 @@ public:
|
||||
NS_ASSERT_OWNINGTHREAD(LSObject);
|
||||
}
|
||||
|
||||
const nsString&
|
||||
DocumentURI() const
|
||||
{
|
||||
return mDocumentURI;
|
||||
}
|
||||
|
||||
LSRequestChild*
|
||||
StartRequest(nsIEventTarget* aMainEventTarget,
|
||||
const LSRequestParams& aParams,
|
||||
@ -162,10 +166,6 @@ private:
|
||||
void
|
||||
DropObserver();
|
||||
|
||||
nsresult
|
||||
GetInfoFromResponse(const LSWriteOpResponse& aResponse,
|
||||
LSNotifyInfo& aInfo);
|
||||
|
||||
void
|
||||
OnChange(const nsAString& aKey,
|
||||
const nsAString& aOldValue,
|
||||
|
320
dom/localstorage/LSSnapshot.cpp
Normal file
320
dom/localstorage/LSSnapshot.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/* -*- 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 "LSSnapshot.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
LSSnapshot::LSSnapshot(LSDatabase* aDatabase)
|
||||
: mDatabase(aDatabase)
|
||||
, mActor(nullptr)
|
||||
, mExactUsage(0)
|
||||
, mPeakUsage(0)
|
||||
#ifdef DEBUG
|
||||
, mInitialized(false)
|
||||
, mSentFinish(false)
|
||||
#endif
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
}
|
||||
|
||||
LSSnapshot::~LSSnapshot()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mDatabase);
|
||||
MOZ_ASSERT_IF(mInitialized, mSentFinish);
|
||||
|
||||
if (mActor) {
|
||||
mActor->SendDeleteMeInternal();
|
||||
MOZ_ASSERT(!mActor, "SendDeleteMeInternal should have cleared!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LSSnapshot::SetActor(LSSnapshotChild* aActor)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aActor);
|
||||
MOZ_ASSERT(!mActor);
|
||||
|
||||
mActor = aActor;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::Init(const LSSnapshotInitInfo& aInitInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
const nsTArray<LSItemInfo>& itemInfos = aInitInfo.itemInfos();
|
||||
for (uint32_t i = 0; i < itemInfos.Length(); i++) {
|
||||
const LSItemInfo& itemInfo = itemInfos[i];
|
||||
mValues.Put(itemInfo.key(), itemInfo.value());
|
||||
}
|
||||
|
||||
mExactUsage = aInitInfo.initialUsage();
|
||||
mPeakUsage = aInitInfo.peakUsage();
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable = this;
|
||||
nsContentUtils::RunInStableState(runnable.forget());
|
||||
|
||||
#ifdef DEBUG
|
||||
mInitialized = true;
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::GetLength(uint32_t* aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
*aResult = mValues.Count();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::GetKey(uint32_t aIndex,
|
||||
nsAString& aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
aResult.SetIsVoid(true);
|
||||
for (auto iter = mValues.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
if (aIndex == 0) {
|
||||
aResult = iter.Key();
|
||||
return NS_OK;
|
||||
}
|
||||
aIndex--;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::GetItem(const nsAString& aKey,
|
||||
nsAString& aResult)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
nsString result;
|
||||
if (!mValues.Get(aKey, &result)) {
|
||||
result.SetIsVoid(true);
|
||||
}
|
||||
|
||||
aResult = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::GetKeys(nsTArray<nsString>& aKeys)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
for (auto iter = mValues.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
aKeys.AppendElement(iter.Key());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::SetItem(const nsAString& aKey,
|
||||
const nsAString& aValue,
|
||||
LSNotifyInfo& aNotifyInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
nsString oldValue;
|
||||
nsresult rv = GetItem(aKey, oldValue);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool changed;
|
||||
if (oldValue == aValue && oldValue.IsVoid() == aValue.IsVoid()) {
|
||||
changed = false;
|
||||
} else {
|
||||
changed = true;
|
||||
|
||||
int64_t delta = static_cast<int64_t>(aValue.Length()) -
|
||||
static_cast<int64_t>(oldValue.Length());
|
||||
|
||||
if (oldValue.IsVoid()) {
|
||||
delta += static_cast<int64_t>(aKey.Length());
|
||||
}
|
||||
|
||||
rv = UpdateUsage(delta);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mValues.Put(aKey, nsString(aValue));
|
||||
|
||||
LSSetItemInfo setItemInfo;
|
||||
setItemInfo.key() = aKey;
|
||||
setItemInfo.oldValue() = oldValue;
|
||||
setItemInfo.value() = aValue;
|
||||
|
||||
mWriteInfos.AppendElement(std::move(setItemInfo));
|
||||
}
|
||||
|
||||
aNotifyInfo.changed() = changed;
|
||||
aNotifyInfo.oldValue() = oldValue;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::RemoveItem(const nsAString& aKey,
|
||||
LSNotifyInfo& aNotifyInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
nsString oldValue;
|
||||
nsresult rv = GetItem(aKey, oldValue);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool changed;
|
||||
if (oldValue.IsVoid()) {
|
||||
changed = false;
|
||||
} else {
|
||||
changed = true;
|
||||
|
||||
int64_t delta = -(static_cast<int64_t>(aKey.Length()) +
|
||||
static_cast<int64_t>(oldValue.Length()));
|
||||
|
||||
DebugOnly<nsresult> rv = UpdateUsage(delta);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
mValues.Remove(aKey);
|
||||
|
||||
LSRemoveItemInfo removeItemInfo;
|
||||
removeItemInfo.key() = aKey;
|
||||
removeItemInfo.oldValue() = oldValue;
|
||||
|
||||
mWriteInfos.AppendElement(std::move(removeItemInfo));
|
||||
}
|
||||
|
||||
aNotifyInfo.changed() = changed;
|
||||
aNotifyInfo.oldValue() = oldValue;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::Clear(LSNotifyInfo& aNotifyInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
bool changed;
|
||||
if (!mValues.Count()) {
|
||||
changed = false;
|
||||
} else {
|
||||
changed = true;
|
||||
|
||||
DebugOnly<nsresult> rv = UpdateUsage(-mExactUsage);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
mValues.Clear();
|
||||
|
||||
LSClearInfo clearInfo;
|
||||
|
||||
mWriteInfos.AppendElement(std::move(clearInfo));
|
||||
}
|
||||
|
||||
aNotifyInfo.changed() = changed;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
LSSnapshot::UpdateUsage(int64_t aDelta)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mDatabase);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mPeakUsage >= mExactUsage);
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
int64_t newExactUsage = mExactUsage + aDelta;
|
||||
if (newExactUsage > mPeakUsage) {
|
||||
int64_t minSize = newExactUsage - mPeakUsage;
|
||||
int64_t requestedSize = minSize + 4096;
|
||||
int64_t size;
|
||||
if (NS_WARN_IF(!mActor->SendIncreasePeakUsage(requestedSize,
|
||||
minSize,
|
||||
&size))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(size >= 0);
|
||||
|
||||
if (size == 0) {
|
||||
return NS_ERROR_FILE_NO_DEVICE_SPACE;
|
||||
}
|
||||
|
||||
mPeakUsage += size;
|
||||
}
|
||||
|
||||
mExactUsage = newExactUsage;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(LSSnapshot, nsIRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
LSSnapshot::Run()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mDatabase);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mSentFinish);
|
||||
|
||||
MOZ_ALWAYS_TRUE(mActor->SendFinish(mWriteInfos));
|
||||
|
||||
#ifdef DEBUG
|
||||
mSentFinish = true;
|
||||
#endif
|
||||
|
||||
mDatabase->NoteFinishedSnapshot(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
96
dom/localstorage/LSSnapshot.h
Normal file
96
dom/localstorage/LSSnapshot.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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_localstorage_LSSnapshot_h
|
||||
#define mozilla_dom_localstorage_LSSnapshot_h
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class LSSnapshotChild;
|
||||
|
||||
class LSSnapshot final
|
||||
: public nsIRunnable
|
||||
{
|
||||
RefPtr<LSDatabase> mDatabase;
|
||||
|
||||
LSSnapshotChild* mActor;
|
||||
|
||||
nsDataHashtable<nsStringHashKey, nsString> mValues;
|
||||
nsTArray<LSWriteInfo> mWriteInfos;
|
||||
|
||||
int64_t mExactUsage;
|
||||
int64_t mPeakUsage;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool mInitialized;
|
||||
bool mSentFinish;
|
||||
#endif
|
||||
|
||||
public:
|
||||
explicit LSSnapshot(LSDatabase* aDatabase);
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(LSSnapshot);
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(LSSnapshotChild* aActor);
|
||||
|
||||
void
|
||||
ClearActor()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
|
||||
mActor = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(const LSSnapshotInitInfo& aInitInfo);
|
||||
|
||||
nsresult
|
||||
GetLength(uint32_t* aResult);
|
||||
|
||||
nsresult
|
||||
GetKey(uint32_t aIndex,
|
||||
nsAString& aResult);
|
||||
|
||||
nsresult
|
||||
GetItem(const nsAString& aKey,
|
||||
nsAString& aResult);
|
||||
|
||||
nsresult
|
||||
GetKeys(nsTArray<nsString>& aKeys);
|
||||
|
||||
nsresult
|
||||
SetItem(const nsAString& aKey,
|
||||
const nsAString& aValue,
|
||||
LSNotifyInfo& aNotifyInfo);
|
||||
|
||||
nsresult
|
||||
RemoveItem(const nsAString& aKey,
|
||||
LSNotifyInfo& aNotifyInfo);
|
||||
|
||||
nsresult
|
||||
Clear(LSNotifyInfo& aNotifyInfo);
|
||||
|
||||
private:
|
||||
~LSSnapshot();
|
||||
|
||||
nsresult
|
||||
UpdateUsage(int64_t aDelta);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_localstorage_LSSnapshot_h
|
@ -186,6 +186,41 @@ namespace dom {
|
||||
|
||||
extern const char16_t* kLocalStorageType;
|
||||
|
||||
class MOZ_STACK_CLASS LSNotifyInfo
|
||||
{
|
||||
bool mChanged;
|
||||
nsString mOldValue;
|
||||
|
||||
public:
|
||||
LSNotifyInfo()
|
||||
: mChanged(false)
|
||||
{ }
|
||||
|
||||
bool
|
||||
changed() const
|
||||
{
|
||||
return mChanged;
|
||||
}
|
||||
|
||||
bool&
|
||||
changed()
|
||||
{
|
||||
return mChanged;
|
||||
}
|
||||
|
||||
const nsString&
|
||||
oldValue() const
|
||||
{
|
||||
return mOldValue;
|
||||
}
|
||||
|
||||
nsString&
|
||||
oldValue()
|
||||
{
|
||||
return mOldValue;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
NextGenLocalStorageEnabled();
|
||||
|
||||
|
@ -3,25 +3,28 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PBackground;
|
||||
include protocol PBackgroundLSSnapshot;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct LSNotifyInfo
|
||||
struct LSItemInfo
|
||||
{
|
||||
bool changed;
|
||||
nsString oldValue;
|
||||
nsString key;
|
||||
nsString value;
|
||||
};
|
||||
|
||||
union LSWriteOpResponse
|
||||
struct LSSnapshotInitInfo
|
||||
{
|
||||
nsresult;
|
||||
LSNotifyInfo;
|
||||
LSItemInfo[] itemInfos;
|
||||
int64_t initialUsage;
|
||||
int64_t peakUsage;
|
||||
};
|
||||
|
||||
sync protocol PBackgroundLSDatabase
|
||||
{
|
||||
manager PBackground;
|
||||
manages PBackgroundLSSnapshot;
|
||||
|
||||
parent:
|
||||
// The DeleteMe message is used to avoid a race condition between the parent
|
||||
@ -37,26 +40,9 @@ parent:
|
||||
|
||||
async AllowToClose();
|
||||
|
||||
sync GetLength()
|
||||
returns (uint32_t length);
|
||||
|
||||
sync GetKey(uint32_t index)
|
||||
returns (nsString key);
|
||||
|
||||
sync GetItem(nsString key)
|
||||
returns (nsString value);
|
||||
|
||||
sync GetKeys()
|
||||
returns (nsString[] keys);
|
||||
|
||||
sync SetItem(nsString documentURI, nsString key, nsString value)
|
||||
returns (LSWriteOpResponse response);
|
||||
|
||||
sync RemoveItem(nsString documentURI, nsString key)
|
||||
returns (LSWriteOpResponse response);
|
||||
|
||||
sync Clear(nsString documentURI)
|
||||
returns (LSWriteOpResponse response);
|
||||
sync PBackgroundLSSnapshot(nsString documentURI,
|
||||
int64_t requestedSize)
|
||||
returns (LSSnapshotInitInfo initInfo);
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
57
dom/localstorage/PBackgroundLSSnapshot.ipdl
Normal file
57
dom/localstorage/PBackgroundLSSnapshot.ipdl
Normal file
@ -0,0 +1,57 @@
|
||||
/* 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 PBackgroundLSDatabase;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct LSSetItemInfo
|
||||
{
|
||||
nsString key;
|
||||
nsString oldValue;
|
||||
nsString value;
|
||||
};
|
||||
|
||||
struct LSRemoveItemInfo
|
||||
{
|
||||
nsString key;
|
||||
nsString oldValue;
|
||||
};
|
||||
|
||||
struct LSClearInfo
|
||||
{
|
||||
};
|
||||
|
||||
union LSWriteInfo
|
||||
{
|
||||
LSSetItemInfo;
|
||||
LSRemoveItemInfo;
|
||||
LSClearInfo;
|
||||
};
|
||||
|
||||
struct LSSnapshotFinishInfo
|
||||
{
|
||||
LSWriteInfo[] writeInfos;
|
||||
};
|
||||
|
||||
sync protocol PBackgroundLSSnapshot
|
||||
{
|
||||
manager PBackgroundLSDatabase;
|
||||
|
||||
parent:
|
||||
async DeleteMe();
|
||||
|
||||
async Finish(LSSnapshotFinishInfo finishInfo);
|
||||
|
||||
sync IncreasePeakUsage(int64_t requestedSize, int64_t minSize)
|
||||
returns (int64_t size);
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -33,6 +33,7 @@ UNIFIED_SOURCES += [
|
||||
'LSDatabase.cpp',
|
||||
'LSObject.cpp',
|
||||
'LSObserver.cpp',
|
||||
'LSSnapshot.cpp',
|
||||
'ReportInternalError.cpp',
|
||||
]
|
||||
|
||||
@ -42,6 +43,7 @@ IPDL_SOURCES += [
|
||||
'PBackgroundLSRequest.ipdl',
|
||||
'PBackgroundLSSharedTypes.ipdlh',
|
||||
'PBackgroundLSSimpleRequest.ipdl',
|
||||
'PBackgroundLSSnapshot.ipdl',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
@ -43,6 +43,13 @@ function finishTest()
|
||||
})
|
||||
}
|
||||
|
||||
function continueToNextStep()
|
||||
{
|
||||
executeSoon(function() {
|
||||
testGenerator.next();
|
||||
});
|
||||
}
|
||||
|
||||
function continueToNextStepSync()
|
||||
{
|
||||
testGenerator.next();
|
||||
|
@ -67,6 +67,11 @@ function* testSteps()
|
||||
|
||||
storages[0].clear();
|
||||
|
||||
// Let the internal snapshot finish (usage is not descreased until all
|
||||
// snapshots finish)..
|
||||
continueToNextStep();
|
||||
yield undefined;
|
||||
|
||||
info("Verifying more data can be written");
|
||||
|
||||
for (let i = 0; i < urls.length; i++) {
|
||||
|
@ -922,19 +922,9 @@ description =
|
||||
description =
|
||||
[PBackgroundStorage::Preload]
|
||||
description =
|
||||
[PBackgroundLSDatabase::GetLength]
|
||||
[PBackgroundLSDatabase::PBackgroundLSSnapshot]
|
||||
description =
|
||||
[PBackgroundLSDatabase::GetKey]
|
||||
description =
|
||||
[PBackgroundLSDatabase::GetItem]
|
||||
description =
|
||||
[PBackgroundLSDatabase::GetKeys]
|
||||
description =
|
||||
[PBackgroundLSDatabase::SetItem]
|
||||
description =
|
||||
[PBackgroundLSDatabase::RemoveItem]
|
||||
description =
|
||||
[PBackgroundLSDatabase::Clear]
|
||||
[PBackgroundLSSnapshot::IncreasePeakUsage]
|
||||
description =
|
||||
[PRemoteSpellcheckEngine::Check]
|
||||
description =
|
||||
|
Loading…
Reference in New Issue
Block a user