GMPStorageParent.cpp (5910B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "GMPStorageParent.h" 7 8 #include "GMPParent.h" 9 #include "gmp-storage.h" 10 11 namespace mozilla { 12 13 #ifdef LOG 14 # undef LOG 15 #endif 16 17 extern LogModule* GetGMPLog(); 18 19 #define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) 20 #define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) 21 22 namespace gmp { 23 24 GMPStorageParent::GMPStorageParent(const nsACString& aNodeId, 25 GMPParent* aPlugin) 26 : mNodeId(aNodeId), mPlugin(aPlugin), mShutdown(true) {} 27 28 nsresult GMPStorageParent::Init() { 29 LOGD(("GMPStorageParent[%p]::Init()", this)); 30 31 if (NS_WARN_IF(mNodeId.IsEmpty())) { 32 return NS_ERROR_FAILURE; 33 } 34 RefPtr<GeckoMediaPluginServiceParent> mps( 35 GeckoMediaPluginServiceParent::GetSingleton()); 36 if (NS_WARN_IF(!mps)) { 37 return NS_ERROR_FAILURE; 38 } 39 40 bool persistent = false; 41 if (NS_WARN_IF( 42 NS_FAILED(mps->IsPersistentStorageAllowed(mNodeId, &persistent)))) { 43 return NS_ERROR_FAILURE; 44 } 45 if (persistent) { 46 mStorage = CreateGMPDiskStorage(mNodeId, mPlugin->GetPluginBaseName()); 47 } else { 48 mStorage = mps->GetMemoryStorageFor(mNodeId, mPlugin->GetPluginBaseName()); 49 } 50 if (!mStorage) { 51 return NS_ERROR_FAILURE; 52 } 53 54 LOGD(("GMPStorageParent[%p]::Init succeeded, nodeId=%s, persistent=%d", this, 55 mNodeId.BeginReading(), persistent)); 56 mShutdown = false; 57 return NS_OK; 58 } 59 60 mozilla::ipc::IPCResult GMPStorageParent::RecvOpen( 61 const nsACString& aRecordName) { 62 LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s')", this, 63 PromiseFlatCString(aRecordName).get())); 64 65 if (mShutdown) { 66 // Shutdown is an expected state, so we do not IPC_FAIL. 67 return IPC_OK(); 68 } 69 70 if (mNodeId.EqualsLiteral("null")) { 71 // Refuse to open storage if the page is opened from local disk, 72 // or shared across origin. 73 LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') failed; null nodeId", 74 this, PromiseFlatCString(aRecordName).get())); 75 (void)SendOpenComplete(aRecordName, GMPGenericErr); 76 return IPC_OK(); 77 } 78 79 if (aRecordName.IsEmpty()) { 80 LOGD(( 81 "GMPStorageParent[%p]::RecvOpen(record='%s') failed; record name empty", 82 this, PromiseFlatCString(aRecordName).get())); 83 (void)SendOpenComplete(aRecordName, GMPGenericErr); 84 return IPC_OK(); 85 } 86 87 if (mStorage->IsOpen(aRecordName)) { 88 LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') failed; record in use", 89 this, PromiseFlatCString(aRecordName).get())); 90 (void)SendOpenComplete(aRecordName, GMPRecordInUse); 91 return IPC_OK(); 92 } 93 94 auto err = mStorage->Open(aRecordName); 95 MOZ_ASSERT(GMP_FAILED(err) || mStorage->IsOpen(aRecordName)); 96 LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') complete; rv=%d", this, 97 PromiseFlatCString(aRecordName).get(), err)); 98 (void)SendOpenComplete(aRecordName, err); 99 100 return IPC_OK(); 101 } 102 103 mozilla::ipc::IPCResult GMPStorageParent::RecvRead( 104 const nsACString& aRecordName) { 105 LOGD(("GMPStorageParent[%p]::RecvRead(record='%s')", this, 106 PromiseFlatCString(aRecordName).get())); 107 108 if (mShutdown) { 109 // Shutdown is an expected state, so we do not IPC_FAIL. 110 return IPC_OK(); 111 } 112 113 nsTArray<uint8_t> data; 114 if (!mStorage->IsOpen(aRecordName)) { 115 LOGD(("GMPStorageParent[%p]::RecvRead(record='%s') failed; record not open", 116 this, PromiseFlatCString(aRecordName).get())); 117 (void)SendReadComplete(aRecordName, GMPClosedErr, data); 118 } else { 119 GMPErr rv = mStorage->Read(aRecordName, data); 120 LOGD( 121 ("GMPStorageParent[%p]::RecvRead(record='%s') read %zu bytes " 122 "rv=%" PRIu32, 123 this, PromiseFlatCString(aRecordName).get(), data.Length(), 124 static_cast<uint32_t>(rv))); 125 (void)SendReadComplete(aRecordName, rv, data); 126 } 127 128 return IPC_OK(); 129 } 130 131 mozilla::ipc::IPCResult GMPStorageParent::RecvWrite( 132 const nsACString& aRecordName, nsTArray<uint8_t>&& aBytes) { 133 LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') %zu bytes", this, 134 PromiseFlatCString(aRecordName).get(), aBytes.Length())); 135 136 if (mShutdown) { 137 // Shutdown is an expected state, so we do not IPC_FAIL. 138 return IPC_OK(); 139 } 140 141 if (!mStorage->IsOpen(aRecordName)) { 142 LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') failed record not open", 143 this, PromiseFlatCString(aRecordName).get())); 144 (void)SendWriteComplete(aRecordName, GMPClosedErr); 145 return IPC_OK(); 146 } 147 148 if (aBytes.Length() > GMP_MAX_RECORD_SIZE) { 149 LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') failed record too big", 150 this, PromiseFlatCString(aRecordName).get())); 151 (void)SendWriteComplete(aRecordName, GMPQuotaExceededErr); 152 return IPC_OK(); 153 } 154 155 GMPErr rv = mStorage->Write(aRecordName, aBytes); 156 LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') write complete rv=%d", 157 this, PromiseFlatCString(aRecordName).get(), rv)); 158 159 (void)SendWriteComplete(aRecordName, rv); 160 161 return IPC_OK(); 162 } 163 164 mozilla::ipc::IPCResult GMPStorageParent::RecvClose( 165 const nsACString& aRecordName) { 166 LOGD(("GMPStorageParent[%p]::RecvClose(record='%s')", this, 167 PromiseFlatCString(aRecordName).get())); 168 169 if (mShutdown) { 170 return IPC_OK(); 171 } 172 173 mStorage->Close(aRecordName); 174 175 return IPC_OK(); 176 } 177 178 void GMPStorageParent::ActorDestroy(ActorDestroyReason aWhy) { 179 LOGD(("GMPStorageParent[%p]::ActorDestroy(reason=%d)", this, aWhy)); 180 Shutdown(); 181 } 182 183 void GMPStorageParent::Shutdown() { 184 if (mShutdown) { 185 return; 186 } 187 188 LOGD(("GMPStorageParent[%p]::Shutdown()", this)); 189 mShutdown = true; 190 (void)SendShutdown(); 191 192 mStorage = nullptr; 193 } 194 195 } // namespace gmp 196 } // namespace mozilla