зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1111787 - Part 1: Delete the directory for the origin pair when "forget this site" is invoked. r=cpearce
This commit is contained in:
Родитель
70996c375b
Коммит
ea65e9fd34
|
@ -32,6 +32,7 @@
|
|||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -63,6 +64,7 @@ GetGMPLog()
|
|||
|
||||
namespace gmp {
|
||||
|
||||
static const uint32_t NodeIdSaltLength = 32;
|
||||
static StaticRefPtr<GeckoMediaPluginService> sSingletonService;
|
||||
|
||||
class GMPServiceCreateHelper MOZ_FINAL : public nsRunnable
|
||||
|
@ -323,16 +325,23 @@ GeckoMediaPluginService::Observe(nsISupports* aSubject,
|
|||
// open a PB mode origin-pair, we'll re-generate new salt.
|
||||
mTempNodeIds.Clear();
|
||||
} else if (!strcmp("gmp-clear-storage", aTopic)) {
|
||||
nsresult rv = GMPDispatch(
|
||||
NS_NewRunnableMethod(this, &GeckoMediaPluginService::ClearStorage));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GeckoMediaPluginService::GMPDispatch(nsIRunnable* event, uint32_t flags)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> r(event);
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = GetThread(getter_AddRefs(thread));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
thread->Dispatch(
|
||||
NS_NewRunnableMethod(this, &GeckoMediaPluginService::ClearStorage),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
return NS_OK;
|
||||
return thread->Dispatch(r, flags);
|
||||
}
|
||||
|
||||
// always call with getter_AddRefs, because it does
|
||||
|
@ -631,28 +640,14 @@ NS_IMETHODIMP
|
|||
GeckoMediaPluginService::AddPluginDirectory(const nsAString& aDirectory)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = GetThread(getter_AddRefs(thread));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> r = new PathRunnable(this, aDirectory, true);
|
||||
thread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
return GMPDispatch(new PathRunnable(this, aDirectory, true));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = GetThread(getter_AddRefs(thread));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> r = new PathRunnable(this, aDirectory, false);
|
||||
thread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
return GMPDispatch(new PathRunnable(this, aDirectory, false));
|
||||
}
|
||||
|
||||
class DummyRunnable : public nsRunnable {
|
||||
|
@ -676,12 +671,8 @@ GeckoMediaPluginService::HasPluginForAPI(const nsACString& aAPI,
|
|||
// cause an event to be dispatched to which scans for plugins. We
|
||||
// dispatch a sync event to the GMP thread here in order to wait until
|
||||
// after the GMP thread has scanned any paths in MOZ_GMP_PATH.
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = GetThread(getter_AddRefs(thread));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
thread->Dispatch(new DummyRunnable(), NS_DISPATCH_SYNC);
|
||||
nsresult rv = GMPDispatch(new DummyRunnable(), NS_DISPATCH_SYNC);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
MOZ_ASSERT(mScannedPluginOnDisk, "Should have scanned MOZ_GMP_PATH by now");
|
||||
}
|
||||
|
||||
|
@ -979,6 +970,14 @@ ReadFromFile(nsIFile* aPath,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ReadSalt(nsIFile* aPath, nsCString& aOutData)
|
||||
{
|
||||
return ReadFromFile(aPath, NS_LITERAL_CSTRING("salt"),
|
||||
aOutData, NodeIdSaltLength);
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginService::IsPersistentStorageAllowed(const nsACString& aNodeId,
|
||||
bool* aOutAllowed)
|
||||
|
@ -1007,7 +1006,6 @@ GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin,
|
|||
#endif
|
||||
|
||||
nsresult rv;
|
||||
const uint32_t NodeIdSaltLength = 32;
|
||||
|
||||
if (aOrigin.EqualsLiteral("null") ||
|
||||
aOrigin.IsEmpty() ||
|
||||
|
@ -1131,10 +1129,7 @@ GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin,
|
|||
}
|
||||
|
||||
} else {
|
||||
rv = ReadFromFile(path,
|
||||
NS_LITERAL_CSTRING("salt"),
|
||||
salt,
|
||||
NodeIdSaltLength);
|
||||
rv = ReadSalt(path, salt);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1146,6 +1141,97 @@ GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
MatchOrigin(nsIFile* aPath, const nsACString& aMatch)
|
||||
{
|
||||
// http://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax
|
||||
static const uint32_t MaxDomainLength = 253;
|
||||
|
||||
nsresult rv;
|
||||
nsCString str;
|
||||
rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("origin"), str, MaxDomainLength);
|
||||
if (NS_SUCCEEDED(rv) && aMatch.Equals(str)) {
|
||||
return true;
|
||||
}
|
||||
rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("topLevelOrigin"), str, MaxDomainLength);
|
||||
if (NS_SUCCEEDED(rv) && aMatch.Equals(str)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginService::ForgetThisSiteOnGMPThread(const nsACString& aOrigin)
|
||||
{
|
||||
#define ERR_RET(x) NS_ENSURE_SUCCESS_VOID(x)
|
||||
#define ERR_CONT(x) if (NS_FAILED(x)) { continue; }
|
||||
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
LOGD(("%s::%s: origin=%s", __CLASS__, __FUNCTION__, aOrigin.Data()));
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> path;
|
||||
|
||||
// $profileDir/gmp/
|
||||
ERR_RET(GetStorageDir(getter_AddRefs(path)));
|
||||
|
||||
// $profileDir/gmp/id/
|
||||
ERR_RET(path->AppendNative(NS_LITERAL_CSTRING("id")));
|
||||
|
||||
// Iterate all sub-folders of $profileDir/gmp/id/
|
||||
nsCOMPtr<nsISimpleEnumerator> iter;
|
||||
ERR_RET(path->GetDirectoryEntries(getter_AddRefs(iter)));
|
||||
|
||||
bool hasMore = false;
|
||||
nsTArray<nsCString> nodeIDsToClear;
|
||||
while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
ERR_CONT(iter->GetNext(getter_AddRefs(supports)));
|
||||
|
||||
// $profileDir/gmp/id/$hash
|
||||
nsCOMPtr<nsIFile> dirEntry(do_QueryInterface(supports, &rv));
|
||||
ERR_CONT(rv);
|
||||
|
||||
// Skip non-directory files.
|
||||
bool isDirectory = false;
|
||||
ERR_CONT(dirEntry->IsDirectory(&isDirectory));
|
||||
if (!isDirectory) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if origin or topLevelOrigin match the origin being forgotten.
|
||||
if (!MatchOrigin(dirEntry, aOrigin)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Keep node IDs to clear data/plugins associated with them later.
|
||||
nsAutoCString salt;
|
||||
if (NS_SUCCEEDED(ReadSalt(dirEntry, salt))) {
|
||||
nodeIDsToClear.AppendElement(salt);
|
||||
}
|
||||
// Now we can remove the directory for the origin pair.
|
||||
if (NS_FAILED(dirEntry->Remove(true))) {
|
||||
NS_WARNING("Failed to delete the directory for the origin pair");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Clear plugins/data associated with the node IDs in nodeIDsToClear
|
||||
// in next patch.
|
||||
nodeIDsToClear.Clear();
|
||||
|
||||
#undef ERR_RET
|
||||
#undef ERR_CONT
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginService::ForgetThisSite(const nsAString& aOrigin)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return GMPDispatch(NS_NewRunnableMethodWithArg<nsCString>(
|
||||
this, &GeckoMediaPluginService::ForgetThisSiteOnGMPThread,
|
||||
NS_ConvertUTF16toUTF8(aOrigin)));
|
||||
}
|
||||
|
||||
class StorageClearedTask : public nsRunnable {
|
||||
public:
|
||||
NS_IMETHOD Run() {
|
||||
|
|
|
@ -52,6 +52,8 @@ public:
|
|||
private:
|
||||
~GeckoMediaPluginService();
|
||||
|
||||
nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL);
|
||||
|
||||
void ClearStorage();
|
||||
|
||||
GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
|
||||
|
@ -74,6 +76,8 @@ private:
|
|||
|
||||
nsresult SetAsyncShutdownTimeout();
|
||||
|
||||
void ForgetThisSiteOnGMPThread(const nsACString& aOrigin);
|
||||
|
||||
protected:
|
||||
friend class GMPParent;
|
||||
void ReAddOnGMPThread(nsRefPtr<GMPParent>& aOld);
|
||||
|
|
|
@ -26,7 +26,7 @@ class GMPVideoHost;
|
|||
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
|
||||
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
|
||||
|
||||
[scriptable, uuid(657443a4-6b5d-4181-98b0-56997b35bd57)]
|
||||
[scriptable, uuid(4aaf58d3-181f-4325-9a2f-41172d995a70)]
|
||||
interface mozIGeckoMediaPluginService : nsISupports
|
||||
{
|
||||
|
||||
|
@ -96,6 +96,11 @@ interface mozIGeckoMediaPluginService : nsISupports
|
|||
in AString topLevelOrigin,
|
||||
in bool inPrivateBrowsingMode);
|
||||
|
||||
/**
|
||||
* Clears storage data associated with the origin.
|
||||
*/
|
||||
void forgetThisSite(in AString origin);
|
||||
|
||||
/**
|
||||
* Returns true if the given node id is allowed to store things
|
||||
* persistently on disk. Private Browsing and local content are not
|
||||
|
|
|
@ -80,6 +80,12 @@ this.ForgetAboutSite = {
|
|||
cm.remove(cookie.host, cookie.name, cookie.path, false);
|
||||
}
|
||||
|
||||
// EME
|
||||
let (mps = Cc["@mozilla.org/gecko-media-plugin-service;1"].
|
||||
getService(Ci.mozIGeckoMediaPluginService)) {
|
||||
mps.forgetThisSite(aDomain);
|
||||
}
|
||||
|
||||
// Plugin data
|
||||
const phInterface = Ci.nsIPluginHost;
|
||||
const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче