summaryrefslogtreecommitdiffstats
path: root/dom/media/gmp/GMPStorageParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/media/gmp/GMPStorageParent.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/dom/media/gmp/GMPStorageParent.cpp b/dom/media/gmp/GMPStorageParent.cpp
new file mode 100644
index 0000000000..d153f5cace
--- /dev/null
+++ b/dom/media/gmp/GMPStorageParent.cpp
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "GMPStorageParent.h"
+#include "GMPParent.h"
+#include "gmp-storage.h"
+#include "mozilla/Unused.h"
+
+namespace mozilla {
+
+#ifdef LOG
+# undef LOG
+#endif
+
+extern LogModule* GetGMPLog();
+
+#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)
+#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg)
+
+namespace gmp {
+
+GMPStorageParent::GMPStorageParent(const nsACString& aNodeId,
+ GMPParent* aPlugin)
+ : mNodeId(aNodeId), mPlugin(aPlugin), mShutdown(true) {}
+
+nsresult GMPStorageParent::Init() {
+ LOGD(("GMPStorageParent[%p]::Init()", this));
+
+ if (NS_WARN_IF(mNodeId.IsEmpty())) {
+ return NS_ERROR_FAILURE;
+ }
+ RefPtr<GeckoMediaPluginServiceParent> mps(
+ GeckoMediaPluginServiceParent::GetSingleton());
+ if (NS_WARN_IF(!mps)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ bool persistent = false;
+ if (NS_WARN_IF(
+ NS_FAILED(mps->IsPersistentStorageAllowed(mNodeId, &persistent)))) {
+ return NS_ERROR_FAILURE;
+ }
+ if (persistent) {
+ mStorage = CreateGMPDiskStorage(mNodeId, mPlugin->GetPluginBaseName());
+ } else {
+ mStorage = mps->GetMemoryStorageFor(mNodeId);
+ }
+ if (!mStorage) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mShutdown = false;
+ return NS_OK;
+}
+
+mozilla::ipc::IPCResult GMPStorageParent::RecvOpen(
+ const nsACString& aRecordName) {
+ LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s')", this,
+ PromiseFlatCString(aRecordName).get()));
+
+ if (mShutdown) {
+ // Shutdown is an expected state, so we do not IPC_FAIL.
+ return IPC_OK();
+ }
+
+ if (mNodeId.EqualsLiteral("null")) {
+ // Refuse to open storage if the page is opened from local disk,
+ // or shared across origin.
+ LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') failed; null nodeId",
+ this, PromiseFlatCString(aRecordName).get()));
+ Unused << SendOpenComplete(aRecordName, GMPGenericErr);
+ return IPC_OK();
+ }
+
+ if (aRecordName.IsEmpty()) {
+ LOGD((
+ "GMPStorageParent[%p]::RecvOpen(record='%s') failed; record name empty",
+ this, PromiseFlatCString(aRecordName).get()));
+ Unused << SendOpenComplete(aRecordName, GMPGenericErr);
+ return IPC_OK();
+ }
+
+ if (mStorage->IsOpen(aRecordName)) {
+ LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') failed; record in use",
+ this, PromiseFlatCString(aRecordName).get()));
+ Unused << SendOpenComplete(aRecordName, GMPRecordInUse);
+ return IPC_OK();
+ }
+
+ auto err = mStorage->Open(aRecordName);
+ MOZ_ASSERT(GMP_FAILED(err) || mStorage->IsOpen(aRecordName));
+ LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') complete; rv=%d", this,
+ PromiseFlatCString(aRecordName).get(), err));
+ Unused << SendOpenComplete(aRecordName, err);
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GMPStorageParent::RecvRead(
+ const nsACString& aRecordName) {
+ LOGD(("GMPStorageParent[%p]::RecvRead(record='%s')", this,
+ PromiseFlatCString(aRecordName).get()));
+
+ if (mShutdown) {
+ // Shutdown is an expected state, so we do not IPC_FAIL.
+ return IPC_OK();
+ }
+
+ nsTArray<uint8_t> data;
+ if (!mStorage->IsOpen(aRecordName)) {
+ LOGD(("GMPStorageParent[%p]::RecvRead(record='%s') failed; record not open",
+ this, PromiseFlatCString(aRecordName).get()));
+ Unused << SendReadComplete(aRecordName, GMPClosedErr, data);
+ } else {
+ GMPErr rv = mStorage->Read(aRecordName, data);
+ LOGD(
+ ("GMPStorageParent[%p]::RecvRead(record='%s') read %zu bytes "
+ "rv=%" PRIu32,
+ this, PromiseFlatCString(aRecordName).get(), data.Length(),
+ static_cast<uint32_t>(rv)));
+ Unused << SendReadComplete(aRecordName, rv, data);
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GMPStorageParent::RecvWrite(
+ const nsACString& aRecordName, nsTArray<uint8_t>&& aBytes) {
+ LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') %zu bytes", this,
+ PromiseFlatCString(aRecordName).get(), aBytes.Length()));
+
+ if (mShutdown) {
+ // Shutdown is an expected state, so we do not IPC_FAIL.
+ return IPC_OK();
+ }
+
+ if (!mStorage->IsOpen(aRecordName)) {
+ LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') failed record not open",
+ this, PromiseFlatCString(aRecordName).get()));
+ Unused << SendWriteComplete(aRecordName, GMPClosedErr);
+ return IPC_OK();
+ }
+
+ if (aBytes.Length() > GMP_MAX_RECORD_SIZE) {
+ LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') failed record too big",
+ this, PromiseFlatCString(aRecordName).get()));
+ Unused << SendWriteComplete(aRecordName, GMPQuotaExceededErr);
+ return IPC_OK();
+ }
+
+ GMPErr rv = mStorage->Write(aRecordName, aBytes);
+ LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') write complete rv=%d",
+ this, PromiseFlatCString(aRecordName).get(), rv));
+
+ Unused << SendWriteComplete(aRecordName, rv);
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GMPStorageParent::RecvClose(
+ const nsACString& aRecordName) {
+ LOGD(("GMPStorageParent[%p]::RecvClose(record='%s')", this,
+ PromiseFlatCString(aRecordName).get()));
+
+ if (mShutdown) {
+ return IPC_OK();
+ }
+
+ mStorage->Close(aRecordName);
+
+ return IPC_OK();
+}
+
+void GMPStorageParent::ActorDestroy(ActorDestroyReason aWhy) {
+ LOGD(("GMPStorageParent[%p]::ActorDestroy(reason=%d)", this, aWhy));
+ Shutdown();
+}
+
+void GMPStorageParent::Shutdown() {
+ LOGD(("GMPStorageParent[%p]::Shutdown()", this));
+
+ if (mShutdown) {
+ return;
+ }
+ mShutdown = true;
+ Unused << SendShutdown();
+
+ mStorage = nullptr;
+}
+
+} // namespace gmp
+} // namespace mozilla