Backed out changeset f93b8ceabc6e (bug 1060179)

This commit is contained in:
Carsten "Tomcat" Book 2014-10-09 12:48:18 +02:00
parent f7bc56c228
commit 131ed8ee36
6 changed files with 84 additions and 322 deletions

View File

@ -711,12 +711,8 @@ GMPParent::DeallocPGMPStorageParent(PGMPStorageParent* aActor)
}
bool
GMPParent::RecvPGMPStorageConstructor(PGMPStorageParent* aActor)
GMPParent::RecvPGMPStorageConstructor(PGMPStorageParent* actor)
{
GMPStorageParent* p = (GMPStorageParent*)aActor;
if (NS_WARN_IF(NS_FAILED(p->Init()))) {
return false;
}
return true;
}

View File

@ -169,7 +169,6 @@ GeckoMediaPluginService::Init()
MOZ_ASSERT(obsService);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "profile-change-teardown", false)));
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false)));
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "last-pb-context-exited", false)));
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
@ -312,13 +311,6 @@ GeckoMediaPluginService::Observe(nsISupports* aSubject,
if (gmpThread) {
gmpThread->Shutdown();
}
} else if (!strcmp("last-pb-context-exited", aTopic)) {
// When Private Browsing mode exits, all we need to do is clear
// mTempNodeIds. This drops all the node ids we've cached in memory
// for PB origin-pairs. If we try to open an origin-pair for non-PB
// mode, we'll get the NodeId salt stored on-disk, and if we try to
// open a PB mode origin-pair, we'll re-generate new salt.
mTempNodeIds.Clear();
}
return NS_OK;
}
@ -965,16 +957,6 @@ ReadFromFile(nsIFile* aPath,
return NS_OK;
}
NS_IMETHODIMP
GeckoMediaPluginService::IsPersistentStorageAllowed(const nsACString& aNodeId,
bool* aOutAllowed)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
NS_ENSURE_ARG(aOutAllowed);
*aOutAllowed = mPersistentStorageAllowed.Get(aNodeId);
return NS_OK;
}
NS_IMETHODIMP
GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
@ -990,44 +972,16 @@ GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin,
nsresult rv;
const uint32_t NodeIdSaltLength = 32;
if (aOrigin.EqualsLiteral("null") ||
if (aInPrivateBrowsing ||
aOrigin.EqualsLiteral("null") ||
aOrigin.IsEmpty() ||
aTopLevelOrigin.EqualsLiteral("null") ||
aTopLevelOrigin.IsEmpty()) {
// At least one of the (origin, topLevelOrigin) is null or empty;
// probably a local file. Generate a random node id, and don't store
// it so that the GMP's storage is temporary and not shared.
// Non-persistent session; just generate a random node id.
nsAutoCString salt;
rv = GenerateRandomPathName(salt, NodeIdSaltLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aOutId = salt;
mPersistentStorageAllowed.Put(salt, false);
return NS_OK;
}
const uint32_t hash = AddToHash(HashString(aOrigin),
HashString(aTopLevelOrigin));
if (aInPrivateBrowsing) {
// For PB mode, we store the node id, indexed by the origin pair,
// so that if the same origin pair is opened in this session, it gets
// the same node id.
nsCString* salt = nullptr;
if (!(salt = mTempNodeIds.Get(hash))) {
// No salt stored, generate and temporarily store some for this id.
nsAutoCString newSalt;
rv = GenerateRandomPathName(newSalt, NodeIdSaltLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
salt = new nsCString(newSalt);
mTempNodeIds.Put(hash, salt);
mPersistentStorageAllowed.Put(*salt, false);
}
aOutId = *salt;
return NS_OK;
return rv;
}
// Otherwise, try to see if we've previously generated and stored salt
@ -1049,6 +1003,8 @@ GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin,
return rv;
}
uint32_t hash = AddToHash(HashString(aOrigin),
HashString(aTopLevelOrigin));
nsAutoCString hashStr;
hashStr.AppendInt((int64_t)hash);
@ -1122,7 +1078,6 @@ GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin,
}
aOutId = salt;
mPersistentStorageAllowed.Put(salt, true);
return NS_OK;
}

View File

@ -17,8 +17,6 @@
#include "nsIThread.h"
#include "nsThreadUtils.h"
#include "nsITimer.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
template <class> struct already_AddRefed;
@ -115,14 +113,6 @@ private:
nsCOMPtr<nsITimer> mAsyncShutdownTimeout; // GMP Thread only.
nsCOMPtr<nsIFile> mStorageBaseDir;
// Hashes of (origin,topLevelOrigin) to the node id for
// non-persistent sessions.
nsClassHashtable<nsUint32HashKey, nsCString> mTempNodeIds;
// Hashes node id to whether that node id is allowed to store data
// persistently on disk.
nsDataHashtable<nsCStringHashKey, bool> mPersistentStorageAllowed;
};
} // namespace gmp

View File

@ -12,12 +12,6 @@
#include "GMPParent.h"
#include "gmp-storage.h"
#include "mozilla/unused.h"
#include "nsTHashtable.h"
#include "nsDataHashtable.h"
#include "prio.h"
#include "mozIGeckoMediaPluginService.h"
#include "nsContentCID.h"
#include "nsServiceManagerUtils.h"
namespace mozilla {
@ -88,6 +82,14 @@ GetGMPStorageDir(nsIFile** aTempDir, const nsCString& aNodeId)
return NS_OK;
}
GMPStorageParent::GMPStorageParent(const nsCString& aNodeId,
GMPParent* aPlugin)
: mNodeId(aNodeId)
, mPlugin(aPlugin)
, mShutdown(false)
{
}
enum OpenFileMode { ReadWrite, Truncate };
nsresult
@ -116,208 +118,11 @@ OpenStorageFile(const nsCString& aRecordName,
return f->OpenNSPRFileDesc(mode, PR_IRWXU, aOutFD);
}
PLDHashOperator
CloseFile(const nsACString& key, PRFileDesc*& entry, void* cx)
{
if (PR_Close(entry) != PR_SUCCESS) {
NS_WARNING("GMPDiskStorage Failed to clsose file.");
}
return PL_DHASH_REMOVE;
}
class GMPDiskStorage : public GMPStorage {
public:
GMPDiskStorage(const nsCString& aNodeId)
: mNodeId(aNodeId)
{
}
~GMPDiskStorage() {
mFiles.Enumerate(CloseFile, nullptr);
MOZ_ASSERT(!mFiles.Count());
}
virtual GMPErr Open(const nsCString& aRecordName) MOZ_OVERRIDE
{
MOZ_ASSERT(!IsOpen(aRecordName));
PRFileDesc* fd = nullptr;
if (NS_FAILED(OpenStorageFile(aRecordName, mNodeId, ReadWrite, &fd))) {
NS_WARNING("Failed to open storage file.");
return GMPGenericErr;
}
mFiles.Put(aRecordName, fd);
return GMPNoErr;
}
virtual bool IsOpen(const nsCString& aRecordName) MOZ_OVERRIDE {
return mFiles.Contains(aRecordName);
}
virtual GMPErr Read(const nsCString& aRecordName,
nsTArray<uint8_t>& aOutBytes) MOZ_OVERRIDE
{
PRFileDesc* fd = mFiles.Get(aRecordName);
if (!fd) {
return GMPGenericErr;
}
int32_t len = PR_Seek(fd, 0, PR_SEEK_END);
PR_Seek(fd, 0, PR_SEEK_SET);
if (len > GMP_MAX_RECORD_SIZE) {
// Refuse to read big records.
return GMPQuotaExceededErr;
}
aOutBytes.SetLength(len);
auto bytesRead = PR_Read(fd, aOutBytes.Elements(), len);
return (bytesRead == len) ? GMPNoErr : GMPGenericErr;
}
virtual GMPErr Write(const nsCString& aRecordName,
const nsTArray<uint8_t>& aBytes) MOZ_OVERRIDE
{
PRFileDesc* fd = mFiles.Get(aRecordName);
if (!fd) {
return GMPGenericErr;
}
// Write operations overwrite the entire record. So re-open the file
// in truncate mode, to clear its contents.
PR_Close(fd);
mFiles.Remove(aRecordName);
if (NS_FAILED(OpenStorageFile(aRecordName, mNodeId, Truncate, &fd))) {
return GMPGenericErr;
}
mFiles.Put(aRecordName, fd);
int32_t bytesWritten = PR_Write(fd, aBytes.Elements(), aBytes.Length());
return (bytesWritten == (int32_t)aBytes.Length()) ? GMPNoErr : GMPGenericErr;
}
virtual void Close(const nsCString& aRecordName) MOZ_OVERRIDE
{
PRFileDesc* fd = mFiles.Get(aRecordName);
if (fd) {
if (PR_Close(fd) == PR_SUCCESS) {
mFiles.Remove(aRecordName);
} else {
NS_WARNING("GMPDiskStorage Failed to clsose file.");
}
}
}
private:
nsDataHashtable<nsCStringHashKey, PRFileDesc*> mFiles;
const nsAutoCString mNodeId;
};
class GMPMemoryStorage : public GMPStorage {
public:
virtual GMPErr Open(const nsCString& aRecordName) MOZ_OVERRIDE
{
MOZ_ASSERT(!IsOpen(aRecordName));
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
record = new Record();
mRecords.Put(aRecordName, record);
}
record->mIsOpen = true;
return GMPNoErr;
}
virtual bool IsOpen(const nsCString& aRecordName) MOZ_OVERRIDE {
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
return false;
}
return record->mIsOpen;
}
virtual GMPErr Read(const nsCString& aRecordName,
nsTArray<uint8_t>& aOutBytes) MOZ_OVERRIDE
{
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
return GMPGenericErr;
}
aOutBytes = record->mData;
return GMPNoErr;
}
virtual GMPErr Write(const nsCString& aRecordName,
const nsTArray<uint8_t>& aBytes) MOZ_OVERRIDE
{
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
return GMPClosedErr;
}
record->mData = aBytes;
return GMPNoErr;
}
virtual void Close(const nsCString& aRecordName) MOZ_OVERRIDE
{
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
return;
}
if (!record->mData.Length()) {
// Record is empty, delete.
mRecords.Remove(aRecordName);
} else {
record->mIsOpen = false;
}
}
private:
struct Record {
Record() : mIsOpen(false) {}
nsTArray<uint8_t> mData;
bool mIsOpen;
};
nsClassHashtable<nsCStringHashKey, Record> mRecords;
};
GMPStorageParent::GMPStorageParent(const nsCString& aNodeId,
GMPParent* aPlugin)
: mNodeId(aNodeId)
, mPlugin(aPlugin)
, mShutdown(false)
{
}
nsresult
GMPStorageParent::Init()
{
if (NS_WARN_IF(mNodeId.IsEmpty())) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
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 = MakeUnique<GMPDiskStorage>(mNodeId);
} else {
mStorage = MakeUnique<GMPMemoryStorage>();
}
return NS_OK;
}
bool
GMPStorageParent::RecvOpen(const nsCString& aRecordName)
{
if (mShutdown) {
return false;
return true;
}
if (mNodeId.EqualsLiteral("null")) {
@ -328,19 +133,21 @@ GMPStorageParent::RecvOpen(const nsCString& aRecordName)
return true;
}
if (aRecordName.IsEmpty()) {
unused << SendOpenComplete(aRecordName, GMPGenericErr);
return true;
}
if (mStorage->IsOpen(aRecordName)) {
if (aRecordName.IsEmpty() || mFiles.Contains(aRecordName)) {
unused << SendOpenComplete(aRecordName, GMPRecordInUse);
return true;
}
auto err = mStorage->Open(aRecordName);
MOZ_ASSERT(GMP_FAILED(err) || mStorage->IsOpen(aRecordName));
unused << SendOpenComplete(aRecordName, err);
PRFileDesc* fd = nullptr;
nsresult rv = OpenStorageFile(aRecordName, mNodeId, ReadWrite, &fd);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to open storage file.");
unused << SendOpenComplete(aRecordName, GMPGenericErr);
return true;
}
mFiles.Put(aRecordName, fd);
unused << SendOpenComplete(aRecordName, GMPNoErr);
return true;
}
@ -351,16 +158,29 @@ GMPStorageParent::RecvRead(const nsCString& aRecordName)
LOGD(("%s::%s: %p record=%s", __CLASS__, __FUNCTION__, this, aRecordName.get()));
if (mShutdown) {
return false;
return true;
}
PRFileDesc* fd = mFiles.Get(aRecordName);
nsTArray<uint8_t> data;
if (!mStorage->IsOpen(aRecordName)) {
if (!fd) {
unused << SendReadComplete(aRecordName, GMPClosedErr, data);
} else {
unused << SendReadComplete(aRecordName, mStorage->Read(aRecordName, data), data);
return true;
}
int32_t len = PR_Seek(fd, 0, PR_SEEK_END);
PR_Seek(fd, 0, PR_SEEK_SET);
if (len > GMP_MAX_RECORD_SIZE) {
// Refuse to read big records.
unused << SendReadComplete(aRecordName, GMPQuotaExceededErr, data);
return true;
}
data.SetLength(len);
auto bytesRead = PR_Read(fd, data.Elements(), len);
auto res = (bytesRead == len) ? GMPNoErr : GMPGenericErr;
unused << SendReadComplete(aRecordName, res, data);
return true;
}
@ -371,21 +191,32 @@ GMPStorageParent::RecvWrite(const nsCString& aRecordName,
LOGD(("%s::%s: %p record=%s", __CLASS__, __FUNCTION__, this, aRecordName.get()));
if (mShutdown) {
return false;
}
if (!mStorage->IsOpen(aRecordName)) {
unused << SendWriteComplete(aRecordName, GMPClosedErr);
return true;
}
if (aBytes.Length() > GMP_MAX_RECORD_SIZE) {
unused << SendWriteComplete(aRecordName, GMPQuotaExceededErr);
return true;
}
unused << SendWriteComplete(aRecordName, mStorage->Write(aRecordName, aBytes));
PRFileDesc* fd = mFiles.Get(aRecordName);
if (!fd) {
unused << SendWriteComplete(aRecordName, GMPGenericErr);
return true;
}
// Write operations overwrite the entire record. So re-open the file
// in truncate mode, to clear its contents.
PR_Close(fd);
mFiles.Remove(aRecordName);
if (NS_FAILED(OpenStorageFile(aRecordName, mNodeId, Truncate, &fd))) {
unused << SendWriteComplete(aRecordName, GMPGenericErr);
return true;
}
mFiles.Put(aRecordName, fd);
int32_t bytesWritten = PR_Write(fd, aBytes.Elements(), aBytes.Length());
auto res = (bytesWritten == (int32_t)aBytes.Length()) ? GMPNoErr : GMPGenericErr;
unused << SendWriteComplete(aRecordName, res);
return true;
}
@ -398,8 +229,12 @@ GMPStorageParent::RecvClose(const nsCString& aRecordName)
return true;
}
mStorage->Close(aRecordName);
PRFileDesc* fd = mFiles.Get(aRecordName);
if (!fd) {
return true;
}
PR_Close(fd);
mFiles.Remove(aRecordName);
return true;
}
@ -410,6 +245,13 @@ GMPStorageParent::ActorDestroy(ActorDestroyReason aWhy)
Shutdown();
}
PLDHashOperator
CloseFile(const nsACString& key, PRFileDesc*& entry, void* cx)
{
PR_Close(entry);
return PL_DHASH_REMOVE;
}
void
GMPStorageParent::Shutdown()
{
@ -421,8 +263,8 @@ GMPStorageParent::Shutdown()
mShutdown = true;
unused << SendShutdown();
mStorage = nullptr;
mFiles.Enumerate(CloseFile, nullptr);
MOZ_ASSERT(!mFiles.Count());
}
} // namespace gmp

View File

@ -8,33 +8,20 @@
#include "mozilla/gmp/PGMPStorageParent.h"
#include "gmp-storage.h"
#include "mozilla/UniquePtr.h"
#include "nsTHashtable.h"
#include "nsDataHashtable.h"
#include "prio.h"
namespace mozilla {
namespace gmp {
class GMPParent;
class GMPStorage {
public:
virtual ~GMPStorage() {}
virtual GMPErr Open(const nsCString& aRecordName) = 0;
virtual bool IsOpen(const nsCString& aRecordName) = 0;
virtual GMPErr Read(const nsCString& aRecordName,
nsTArray<uint8_t>& aOutBytes) = 0;
virtual GMPErr Write(const nsCString& aRecordName,
const nsTArray<uint8_t>& aBytes) = 0;
virtual void Close(const nsCString& aRecordName) = 0;
};
class GMPStorageParent : public PGMPStorageParent {
public:
NS_INLINE_DECL_REFCOUNTING(GMPStorageParent)
GMPStorageParent(const nsCString& aNodeId,
GMPParent* aPlugin);
GMPStorageParent(const nsCString& aNodeId, GMPParent* aPlugin);
nsresult Init();
void Shutdown();
protected:
@ -48,9 +35,8 @@ protected:
private:
~GMPStorageParent() {}
UniquePtr<GMPStorage> mStorage;
const nsCString mNodeId;
nsDataHashtable<nsCStringHashKey, PRFileDesc*> mFiles;
const nsAutoCString mNodeId;
nsRefPtr<GMPParent> mPlugin;
bool mShutdown;
};

View File

@ -26,7 +26,7 @@ class GMPVideoHost;
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
[scriptable, uuid(b350d3b6-00c9-4602-bdfe-84c2be8d1e7a)]
[scriptable, uuid(e5cde76d-f926-4b3f-84ff-62864c7a750a)]
interface mozIGeckoMediaPluginService : nsISupports
{
@ -98,13 +98,6 @@ interface mozIGeckoMediaPluginService : nsISupports
in AString topLevelOrigin,
in bool inPrivateBrowsingMode);
/**
* Returns true if the given node id is allowed to store things
* persistently on disk. Private Browsing and local content are not
* allowed to store persistent data.
*/
bool isPersistentStorageAllowed(in ACString nodeId);
/**
* Returns the directory to use as the base for storing data about GMPs.
*/