summaryrefslogtreecommitdiffstats
path: root/dom/media/mediacapabilities/KeyValueStorage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/mediacapabilities/KeyValueStorage.cpp')
-rw-r--r--dom/media/mediacapabilities/KeyValueStorage.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/dom/media/mediacapabilities/KeyValueStorage.cpp b/dom/media/mediacapabilities/KeyValueStorage.cpp
new file mode 100644
index 0000000000..f0ac0aad7d
--- /dev/null
+++ b/dom/media/mediacapabilities/KeyValueStorage.cpp
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "KeyValueStorage.h"
+
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsVariant.h"
+
+namespace mozilla {
+
+class DatabaseCallback final : public nsIKeyValueDatabaseCallback {
+ public:
+ NS_DECL_ISUPPORTS
+
+ explicit DatabaseCallback(RefPtr<nsIKeyValueDatabase>& aDatabase)
+ : mDatabase(aDatabase) {}
+ NS_IMETHOD Resolve(nsIKeyValueDatabase* aDatabase) override {
+ if (!aDatabase) {
+ mResultPromise.Reject(NS_ERROR_FAILURE, __func__);
+ }
+ mDatabase = aDatabase;
+ mResultPromise.Resolve(true, __func__);
+ return NS_OK;
+ }
+ NS_IMETHOD Reject(const nsACString&) override {
+ mResultPromise.Reject(NS_ERROR_FAILURE, __func__);
+ return NS_OK;
+ }
+ RefPtr<GenericPromise> Ensure() { return mResultPromise.Ensure(__func__); }
+
+ protected:
+ ~DatabaseCallback() = default;
+ RefPtr<nsIKeyValueDatabase>& mDatabase;
+ MozPromiseHolder<GenericPromise> mResultPromise;
+};
+NS_IMPL_ISUPPORTS(DatabaseCallback, nsIKeyValueDatabaseCallback);
+
+RefPtr<GenericPromise> KeyValueStorage::Init() {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!mDatabaseName.IsEmpty());
+ nsresult rv;
+
+ nsCOMPtr<nsIFile> profileDir;
+ rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
+ getter_AddRefs(profileDir));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ }
+ MOZ_ASSERT(profileDir);
+
+ rv = profileDir->AppendNative("mediacapabilities"_ns);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ }
+
+ rv = profileDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
+ if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ }
+
+ nsCOMPtr<nsIKeyValueService> keyValueService =
+ do_GetService("@mozilla.org/key-value-service;1", &rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ }
+ MOZ_ASSERT(keyValueService);
+
+ auto callback = MakeRefPtr<DatabaseCallback>(mDatabase);
+
+ nsString path;
+ profileDir->GetPath(path);
+ keyValueService->GetOrCreate(callback, NS_ConvertUTF16toUTF8(path),
+ mDatabaseName);
+ return callback->Ensure();
+}
+
+class VoidCallback final : public nsIKeyValueVoidCallback {
+ public:
+ NS_DECL_ISUPPORTS
+
+ explicit VoidCallback(const RefPtr<KeyValueStorage>& aOwner)
+ : nsIKeyValueVoidCallback(), mOwner(aOwner) {}
+
+ NS_IMETHOD Resolve() override {
+ mResultPromise.Resolve(true, __func__);
+ return NS_OK;
+ }
+ NS_IMETHOD Reject(const nsACString&) override {
+ mResultPromise.Reject(NS_ERROR_FAILURE, __func__);
+ return NS_OK;
+ }
+ RefPtr<GenericPromise> Ensure(const char* aMethodName) {
+ return mResultPromise.Ensure(aMethodName);
+ }
+
+ protected:
+ ~VoidCallback() = default;
+ MozPromiseHolder<GenericPromise> mResultPromise;
+ RefPtr<KeyValueStorage> mOwner;
+};
+NS_IMPL_ISUPPORTS(VoidCallback, nsIKeyValueVoidCallback);
+
+RefPtr<GenericPromise> KeyValueStorage::Put(const nsACString& aKey,
+ int32_t aValue) {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mDatabase);
+ MOZ_ASSERT(!mDatabaseName.IsEmpty());
+
+ auto value = MakeRefPtr<nsVariant>();
+ nsresult rv = value->SetAsInt32(aValue);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ }
+
+ auto callback = MakeRefPtr<VoidCallback>(this);
+ rv = mDatabase->Put(callback, aKey, value);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ }
+ return callback->Ensure(__func__);
+}
+
+RefPtr<GenericPromise> KeyValueStorage::Put(const nsACString& aName,
+ const nsACString& aKey,
+ int32_t aValue) {
+ if (!mDatabase || !mDatabaseName.Equals(aName)) {
+ mDatabaseName = aName;
+ RefPtr<KeyValueStorage> self = this;
+ const nsCString key(aKey);
+ return Init()->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [self, key, aValue](bool) { return self->Put(key, aValue); },
+ [](nsresult rv) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ });
+ }
+ return Put(aKey, aValue);
+}
+
+class GetValueCallback final : public nsIKeyValueVariantCallback {
+ public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Resolve(nsIVariant* aResult) override {
+ int32_t value = 0;
+ Unused << aResult->GetAsInt32(&value);
+ mResultPromise.Resolve(value, __func__);
+ return NS_OK;
+ }
+ NS_IMETHOD Reject(const nsACString&) override {
+ mResultPromise.Reject(NS_ERROR_FAILURE, __func__);
+ return NS_OK;
+ }
+ RefPtr<KeyValueStorage::GetPromise> Ensure() {
+ return mResultPromise.Ensure(__func__);
+ }
+
+ protected:
+ ~GetValueCallback() = default;
+
+ private:
+ MozPromiseHolder<KeyValueStorage::GetPromise> mResultPromise;
+};
+NS_IMPL_ISUPPORTS(GetValueCallback, nsIKeyValueVariantCallback);
+
+RefPtr<KeyValueStorage::GetPromise> KeyValueStorage::Get(
+ const nsACString& aKey) {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mDatabase);
+ MOZ_ASSERT(!mDatabaseName.IsEmpty());
+
+ RefPtr<nsVariant> defaultValue = new nsVariant;
+ nsresult rv = defaultValue->SetAsInt32(-1);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return KeyValueStorage::GetPromise::CreateAndReject(rv, __func__);
+ }
+
+ auto callback = MakeRefPtr<GetValueCallback>();
+ rv = mDatabase->Get(callback, aKey, defaultValue);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return KeyValueStorage::GetPromise::CreateAndReject(rv, __func__);
+ }
+ return callback->Ensure();
+}
+
+RefPtr<KeyValueStorage::GetPromise> KeyValueStorage::Get(
+ const nsACString& aName, const nsACString& aKey) {
+ if (!mDatabase || !mDatabaseName.Equals(aName)) {
+ mDatabaseName = aName;
+ RefPtr<KeyValueStorage> self = this;
+ const nsCString key(aKey);
+ return Init()->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [self, key](bool) { return self->Get(key); },
+ [](nsresult rv) {
+ return KeyValueStorage::GetPromise::CreateAndReject(rv, __func__);
+ });
+ }
+ return Get(aKey);
+}
+
+RefPtr<GenericPromise> KeyValueStorage::Clear() {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mDatabase);
+ MOZ_ASSERT(!mDatabaseName.IsEmpty());
+
+ auto callback = MakeRefPtr<VoidCallback>(this);
+ nsresult rv = mDatabase->Clear(callback);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ }
+ return callback->Ensure(__func__);
+}
+
+RefPtr<GenericPromise> KeyValueStorage::Clear(const nsACString& aName) {
+ if (!mDatabase || !mDatabaseName.Equals(aName)) {
+ mDatabaseName = aName;
+ RefPtr<KeyValueStorage> self = this;
+ return Init()->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [self](bool) { return self->Clear(); },
+ [](nsresult rv) {
+ return GenericPromise::CreateAndReject(rv, __func__);
+ });
+ }
+ return Clear();
+}
+
+} // namespace mozilla