Bug 1705034 - Implemented ForgetThisBaseDomain in GMPServiceParent. r=pbz,bryce

Differential Revision: https://phabricator.services.mozilla.com/D116412
This commit is contained in:
Stefan Zabka 2021-07-07 10:51:59 +00:00
Родитель 6fc3e06d85
Коммит 7bdc63c79c
5 изменённых файлов: 381 добавлений и 44 удалений

Просмотреть файл

@ -32,6 +32,7 @@
#include "nsComponentManagerUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsNetUtil.h"
#include "nsHashKeys.h"
#include "nsIFile.h"
#include "nsIObserverService.h"
@ -971,7 +972,7 @@ GeckoMediaPluginServiceParent::GetStorageDir(nsIFile** aOutFile) {
return mStorageBaseDir->Clone(aOutFile);
}
static nsresult WriteToFile(nsIFile* aPath, const nsCString& aFileName,
nsresult WriteToFile(nsIFile* aPath, const nsCString& aFileName,
const nsCString& aData) {
nsCOMPtr<nsIFile> path;
nsresult rv = aPath->Clone(getter_AddRefs(path));
@ -1248,37 +1249,54 @@ static bool ExtractHostName(const nsACString& aOrigin, nsACString& aOutData) {
return true;
}
constexpr uint32_t kMaxDomainLength = 253;
// http://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax
constexpr std::array<nsLiteralCString, 2> kFileNames = {"origin"_ns,
"topLevelOrigin"_ns};
bool MatchOrigin(nsIFile* aPath, const nsACString& aSite,
const mozilla::OriginAttributesPattern& aPattern) {
// http://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax
static const uint32_t MaxDomainLength = 253;
nsresult rv;
nsCString str;
nsCString originNoSuffix;
mozilla::OriginAttributes originAttributes;
for (const auto& fileName : kFileNames) {
rv = ReadFromFile(aPath, fileName, str, kMaxDomainLength);
if (!originAttributes.PopulateFromOrigin(str, originNoSuffix)) {
// Fails on parsing the originAttributes, treat this as a non-match.
return false;
}
rv = ReadFromFile(aPath, "origin"_ns, str, MaxDomainLength);
if (!originAttributes.PopulateFromOrigin(str, originNoSuffix)) {
// Fails on parsing the originAttributes, treat this as a non-match.
return false;
if (NS_SUCCEEDED(rv) && ExtractHostName(originNoSuffix, str) &&
str.Equals(aSite) && aPattern.Matches(originAttributes)) {
return true;
}
}
return false;
}
if (NS_SUCCEEDED(rv) && ExtractHostName(originNoSuffix, str) &&
str.Equals(aSite) && aPattern.Matches(originAttributes)) {
return true;
}
mozilla::OriginAttributes topLevelOriginAttributes;
rv = ReadFromFile(aPath, "topLevelOrigin"_ns, str, MaxDomainLength);
if (!topLevelOriginAttributes.PopulateFromOrigin(str, originNoSuffix)) {
// Fails on paring the originAttributes, treat this as a non-match.
return false;
}
if (NS_SUCCEEDED(rv) && ExtractHostName(originNoSuffix, str) &&
str.Equals(aSite) && aPattern.Matches(topLevelOriginAttributes)) {
return true;
bool MatchBaseDomain(nsIFile* aPath, const nsACString& aBaseDomain) {
nsresult rv;
nsCString fileContent;
nsCString originNoSuffix;
mozilla::OriginAttributes originAttributes;
for (const auto& fileName : kFileNames) {
rv = ReadFromFile(aPath, fileName, fileContent, kMaxDomainLength);
if (NS_FAILED(rv) ||
!originAttributes.PopulateFromOrigin(fileContent, originNoSuffix)) {
// Fails on parsing the originAttributes, treat this as a non-match.
return false;
}
nsCString originHostname;
if (!ExtractHostName(originNoSuffix, originHostname)) {
return false;
}
bool success;
rv = NS_HasRootDomain(originHostname, aBaseDomain, &success);
if (NS_SUCCEEDED(rv) && success) {
return true;
}
}
return false;
}
@ -1413,6 +1431,26 @@ void GeckoMediaPluginServiceParent::ForgetThisSiteOnGMPThread(
ClearNodeIdAndPlugin(filter);
}
void GeckoMediaPluginServiceParent::ForgetThisBaseDomainOnGMPThread(
const nsACString& aBaseDomain) {
MOZ_ASSERT(mGMPThread->IsOnCurrentThread());
GMP_LOG_DEBUG("%s::%s: baseDomain=%s", __CLASS__, __FUNCTION__,
aBaseDomain.Data());
struct BaseDomainFilter : public DirectoryFilter {
explicit BaseDomainFilter(const nsACString& aBaseDomain)
: mBaseDomain(aBaseDomain) {}
bool operator()(nsIFile* aPath) override {
return MatchBaseDomain(aPath, mBaseDomain);
}
private:
const nsACString& mBaseDomain;
} filter(aBaseDomain);
ClearNodeIdAndPlugin(filter);
}
void GeckoMediaPluginServiceParent::ClearRecentHistoryOnGMPThread(
PRTime aSince) {
MOZ_ASSERT(mGMPThread->IsOnCurrentThread());
@ -1504,6 +1542,24 @@ nsresult GeckoMediaPluginServiceParent::ForgetThisSiteNative(
NS_ConvertUTF16toUTF8(aSite), aPattern));
}
NS_IMETHODIMP
GeckoMediaPluginServiceParent::ForgetThisBaseDomain(
const nsAString& aBaseDomain) {
MOZ_ASSERT(NS_IsMainThread());
return ForgetThisBaseDomainNative(aBaseDomain);
}
nsresult GeckoMediaPluginServiceParent::ForgetThisBaseDomainNative(
const nsAString& aBaseDomain) {
MOZ_ASSERT(NS_IsMainThread());
return GMPDispatch(NewRunnableMethod<nsCString>(
"gmp::GeckoMediaPluginServiceParent::ForgetThisBaseDomainOnGMPThread",
this, &GeckoMediaPluginServiceParent::ForgetThisBaseDomainOnGMPThread,
NS_ConvertUTF16toUTF8(aBaseDomain)));
}
static bool IsNodeIdValid(GMPParent* aParent) {
return !aParent->GetNodeId().IsEmpty();
}

Просмотреть файл

@ -12,6 +12,7 @@
#include "nsClassHashtable.h"
#include "nsTHashMap.h"
#include "mozilla/Atomics.h"
#include "nsNetUtil.h"
#include "nsIAsyncShutdown.h"
#include "nsRefPtrHashtable.h"
#include "nsThreadUtils.h"
@ -63,6 +64,8 @@ class GeckoMediaPluginServiceParent final
nsresult ForgetThisSiteNative(
const nsAString& aSite, const mozilla::OriginAttributesPattern& aPattern);
nsresult ForgetThisBaseDomainNative(const nsAString& aBaseDomain);
// Notifies that some user of this class is created/destroyed.
void ServiceUserCreated(GMPServiceParent* aServiceParent);
void ServiceUserDestroyed(GMPServiceParent* aServiceParent);
@ -102,8 +105,9 @@ class GeckoMediaPluginServiceParent final
void ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir,
DirectoryFilter& aFilter);
void ForgetThisSiteOnGMPThread(
const nsACString& aOrigin,
const nsACString& aSite,
const mozilla::OriginAttributesPattern& aPattern);
void ForgetThisBaseDomainOnGMPThread(const nsACString& aBaseDomain);
void ClearRecentHistoryOnGMPThread(PRTime aSince);
already_AddRefed<GMPParent> GetById(uint32_t aPluginId);
@ -208,9 +212,12 @@ class GeckoMediaPluginServiceParent final
nsTArray<GMPServiceParent*> mServiceParents;
};
nsresult WriteToFile(nsIFile* aPath, const nsCString& aFileName,
const nsCString& aData);
nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData);
bool MatchOrigin(nsIFile* aPath, const nsACString& aSite,
const mozilla::OriginAttributesPattern& aPattern);
bool MatchBaseDomain(nsIFile* aPath, const nsACString& aBaseDomain);
class GMPServiceParent final : public PGMPServiceParent {
public:

Просмотреть файл

@ -36,6 +36,13 @@ interface mozIGeckoMediaPluginChromeService : nsISupports
void forgetThisSite(in AString site,
in AString aPattern);
/**
* Clears storage data associated with the base domain
* This means cleaning any storage that is associated
* either by origin or top level origin with the base domain
*/
void forgetThisBaseDomain(in AString baseDomain);
/**
* Returns true if the given node id is allowed to store things
* persistently on disk. Private Browsing and local content are not

Просмотреть файл

@ -14,6 +14,9 @@
#include "mozilla/SchedulerGroup.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "nsIFile.h"
#include "nsCRTGlue.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsNSSComponent.h" //For EnsureNSSInitializedChromeOrContent
#include "nsThreadUtils.h"
@ -473,7 +476,7 @@ class CDMStorageTest {
: siteToForget(aSite), mPattern(aPattern) {}
nsCString siteToForget;
mozilla::OriginAttributesPattern mPattern;
nsTArray<nsCString> expectedRemainingNodeIds;
nsTArray<nsCString> mExpectedRemainingNodeIds;
};
class NodeIdCollector {
@ -484,7 +487,7 @@ class CDMStorageTest {
nsresult rv = ReadSalt(aFile, salt);
ASSERT_TRUE(NS_SUCCEEDED(rv));
if (!MatchOrigin(aFile, mNodeInfo->siteToForget, mNodeInfo->mPattern)) {
mNodeInfo->expectedRemainingNodeIds.AppendElement(salt);
mNodeInfo->mExpectedRemainingNodeIds.AppendElement(salt);
}
}
@ -530,18 +533,26 @@ class CDMStorageTest {
public:
explicit NodeIdVerifier(const NodeInfo* aInfo)
: mNodeInfo(aInfo),
mExpectedRemainingNodeIds(aInfo->expectedRemainingNodeIds.Clone()) {}
mExpectedRemainingNodeIds(aInfo->mExpectedRemainingNodeIds.Clone()) {}
void operator()(nsIFile* aFile) {
nsCString salt;
nsresult rv = ReadSalt(aFile, salt);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Shouldn't match the origin if we clear correctly.
EXPECT_FALSE(
MatchOrigin(aFile, mNodeInfo->siteToForget, mNodeInfo->mPattern));
MatchOrigin(aFile, mNodeInfo->siteToForget, mNodeInfo->mPattern))
<< "Found files persisted that match against a site that should "
"have been removed!";
// Check if remaining nodeIDs are as expected.
EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt));
EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt))
<< "Failed to remove salt from expected remaining node ids. This "
"indicates storage that should be forgotten is still persisted!";
}
~NodeIdVerifier() {
EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty())
<< "Some expected remaining node ids were not checked against. This "
"indicates that data we expected to find in storage was missing!";
}
~NodeIdVerifier() { EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty()); }
private:
const NodeInfo* mNodeInfo;
@ -551,14 +562,20 @@ class CDMStorageTest {
class StorageVerifier {
public:
explicit StorageVerifier(const NodeInfo* aInfo)
: mExpectedRemainingNodeIds(aInfo->expectedRemainingNodeIds.Clone()) {}
: mExpectedRemainingNodeIds(aInfo->mExpectedRemainingNodeIds.Clone()) {}
void operator()(nsIFile* aFile) {
nsCString salt;
nsresult rv = aFile->GetNativeLeafName(salt);
ASSERT_TRUE(NS_SUCCEEDED(rv));
EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt));
EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt))
<< "Failed to remove salt from expected remaining node ids. This "
"indicates storage that should be forgotten is still persisted!";
}
~StorageVerifier() {
EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty())
<< "Some expected remaining node ids were not checked against. This "
"indicates that data we expected to find in storage was missing!";
}
~StorageVerifier() { EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty()); }
private:
nsTArray<nsCString> mExpectedRemainingNodeIds;
@ -573,6 +590,178 @@ class CDMStorageTest {
EXPECT_TRUE(NS_SUCCEEDED(rv));
}
/**
* 1. Generate storage data for some sites.
* 2. Forget about base domain example1.com
* 3. Check if the storage data for the forgotten site are erased correctly.
* 4. Check if the storage data for other sites remain unchanged.
*/
void TestForgetThisBaseDomain() {
AssertIsOnGMPThread();
EXPECT_TRUE(IsCDMStorageIsEmpty());
// Generate storage data for some site.
nsCOMPtr<nsIRunnable> r = NewRunnableMethod(
"CDMStorageTest::TestForgetThisBaseDomain_SecondSite", this,
&CDMStorageTest::TestForgetThisBaseDomain_SecondSite);
Expect("test-storage complete"_ns, r.forget());
CreateDecryptor(u"http://media.example1.com"_ns,
u"http://tld.example2.com"_ns, false, "test-storage"_ns);
}
void TestForgetThisBaseDomain_SecondSite() {
Shutdown();
// Generate storage data for another site.
nsCOMPtr<nsIRunnable> r = NewRunnableMethod(
"CDMStorageTest::TestForgetThisBaseDomain_ThirdSite", this,
&CDMStorageTest::TestForgetThisBaseDomain_ThirdSite);
Expect("test-storage complete"_ns, r.forget());
CreateDecryptor(u"http://media.somewhereelse.com"_ns,
u"http://home.example1.com"_ns, false, "test-storage"_ns);
}
void TestForgetThisBaseDomain_ThirdSite() {
Shutdown();
// Generate storage data for another site.
nsCOMPtr<nsIRunnable> r = NewRunnableMethod(
"CDMStorageTest::TestForgetThisBaseDomain_CollectSiteInfo", this,
&CDMStorageTest::TestForgetThisBaseDomain_CollectSiteInfo);
Expect("test-storage complete"_ns, r.forget());
CreateDecryptor(u"http://media.example3.com"_ns,
u"http://tld.long-example1.com"_ns, false,
"test-storage"_ns);
}
struct BaseDomainNodeInfo {
explicit BaseDomainNodeInfo(const nsACString& aBaseDomain)
: baseDomainToForget(aBaseDomain) {}
nsCString baseDomainToForget;
nsTArray<nsCString> mExpectedRemainingNodeIds;
};
class BaseDomainNodeIdCollector {
public:
explicit BaseDomainNodeIdCollector(BaseDomainNodeInfo* aInfo)
: mNodeInfo(aInfo) {}
void operator()(nsIFile* aFile) {
nsCString salt;
nsresult rv = ReadSalt(aFile, salt);
ASSERT_TRUE(NS_SUCCEEDED(rv));
if (!MatchBaseDomain(aFile, mNodeInfo->baseDomainToForget)) {
mNodeInfo->mExpectedRemainingNodeIds.AppendElement(salt);
}
}
private:
BaseDomainNodeInfo* mNodeInfo;
};
void TestForgetThisBaseDomain_CollectSiteInfo() {
UniquePtr<BaseDomainNodeInfo> siteInfo(
new BaseDomainNodeInfo("example1.com"_ns));
// Collect nodeIds that are expected to remain for later comparison.
EnumerateCDMStorageDir("id"_ns, BaseDomainNodeIdCollector(siteInfo.get()));
// Invoke "ForgetThisBaseDomain" on the main thread.
SchedulerGroup::Dispatch(
TaskCategory::Other,
NewRunnableMethod<UniquePtr<BaseDomainNodeInfo>&&>(
"CDMStorageTest::TestForgetThisBaseDomain_Forget", this,
&CDMStorageTest::TestForgetThisBaseDomain_Forget,
std::move(siteInfo)));
}
void TestForgetThisBaseDomain_Forget(
UniquePtr<BaseDomainNodeInfo>&& aSiteInfo) {
RefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginServiceParent::GetSingleton();
service->ForgetThisBaseDomain(
NS_ConvertUTF8toUTF16(aSiteInfo->baseDomainToForget));
nsCOMPtr<nsIThread> thread;
service->GetThread(getter_AddRefs(thread));
nsCOMPtr<nsIRunnable> r =
NewRunnableMethod<UniquePtr<BaseDomainNodeInfo>&&>(
"CDMStorageTest::TestForgetThisBaseDomain_Verify", this,
&CDMStorageTest::TestForgetThisBaseDomain_Verify,
std::move(aSiteInfo));
thread->Dispatch(r, NS_DISPATCH_NORMAL);
nsCOMPtr<nsIRunnable> f = NewRunnableMethod(
"CDMStorageTest::SetFinished", this, &CDMStorageTest::SetFinished);
thread->Dispatch(f, NS_DISPATCH_NORMAL);
}
class BaseDomainNodeIdVerifier {
public:
explicit BaseDomainNodeIdVerifier(const BaseDomainNodeInfo* aInfo)
: mNodeInfo(aInfo),
mExpectedRemainingNodeIds(aInfo->mExpectedRemainingNodeIds.Clone()) {}
void operator()(nsIFile* aFile) {
nsCString salt;
nsresult rv = ReadSalt(aFile, salt);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Shouldn't match the origin if we clear correctly.
EXPECT_FALSE(MatchBaseDomain(aFile, mNodeInfo->baseDomainToForget))
<< "Found files persisted that match against a domain that should "
"have been removed!";
// Check if remaining nodeIDs are as expected.
EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt))
<< "Failed to remove salt from expected remaining node ids. This "
"indicates storage that should be forgotten is still persisted!";
}
~BaseDomainNodeIdVerifier() {
EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty())
<< "Some expected remaining node ids were not checked against. This "
"indicates that data we expected to find in storage was missing!";
}
private:
const BaseDomainNodeInfo* mNodeInfo;
nsTArray<nsCString> mExpectedRemainingNodeIds;
};
class BaseDomainStorageVerifier {
public:
explicit BaseDomainStorageVerifier(const BaseDomainNodeInfo* aInfo)
: mExpectedRemainingNodeIds(aInfo->mExpectedRemainingNodeIds.Clone()) {}
void operator()(nsIFile* aFile) {
nsCString salt;
nsresult rv = aFile->GetNativeLeafName(salt);
ASSERT_TRUE(NS_SUCCEEDED(rv));
EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt))
<< "Failed to remove salt from expected remaining node ids. This "
"indicates storage that should be forgotten is still persisted!";
;
}
~BaseDomainStorageVerifier() {
EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty())
<< "Some expected remaining node ids were not checked against. This "
"indicates that data we expected to find in storage was missing!";
;
}
private:
nsTArray<nsCString> mExpectedRemainingNodeIds;
};
void TestForgetThisBaseDomain_Verify(
UniquePtr<BaseDomainNodeInfo>&& aSiteInfo) {
nsresult rv = EnumerateCDMStorageDir(
"id"_ns, BaseDomainNodeIdVerifier(aSiteInfo.get()));
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = EnumerateCDMStorageDir("storage"_ns,
BaseDomainStorageVerifier(aSiteInfo.get()));
EXPECT_TRUE(NS_SUCCEEDED(rv));
}
/**
* 1. Generate some storage data.
* 2. Find the max mtime |t| in $profileDir/gmp/$platform/gmp-fake/id/.
@ -1013,6 +1202,70 @@ class CDMStorageTest {
UniquePtr<CallbackProxy> mCallback;
}; // class CDMStorageTest
static nsresult CreateTestDirectory(nsCOMPtr<nsIFile>& aOut) {
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(aOut));
if (NS_FAILED(rv)) {
return rv;
}
nsCString dirName;
dirName.SetLength(32);
NS_MakeRandomString(dirName.BeginWriting(), 32);
aOut->Append(NS_ConvertUTF8toUTF16(dirName));
rv = aOut->Create(nsIFile::DIRECTORY_TYPE, 0755);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
void TestMatchBaseDomain_MatchOrigin() {
nsCOMPtr<nsIFile> testDir;
nsresult rv = CreateTestDirectory(testDir);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = WriteToFile(testDir, "origin"_ns,
"https://video.subdomain.removeme.github.io"_ns);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = WriteToFile(testDir, "topLevelOrigin"_ns,
"https://embedder.example.com"_ns);
EXPECT_TRUE(NS_SUCCEEDED(rv));
bool result = MatchBaseDomain(testDir, "removeme.github.io"_ns);
EXPECT_TRUE(result);
testDir->Remove(true);
}
void TestMatchBaseDomain_MatchTLD() {
nsCOMPtr<nsIFile> testDir;
nsresult rv = CreateTestDirectory(testDir);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = WriteToFile(testDir, "origin"_ns,
"https://video.example.com^userContextId=4"_ns);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = WriteToFile(testDir, "topLevelOrigin"_ns,
"https://evil.web.megacorp.co.uk^privateBrowsingId=1"_ns);
EXPECT_TRUE(NS_SUCCEEDED(rv));
bool result = MatchBaseDomain(testDir, "megacorp.co.uk"_ns);
EXPECT_TRUE(result);
testDir->Remove(true);
}
void TestMatchBaseDomain_NoMatch() {
nsCOMPtr<nsIFile> testDir;
nsresult rv = CreateTestDirectory(testDir);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = WriteToFile(testDir, "origin"_ns,
"https://video.example.com^userContextId=4"_ns);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = WriteToFile(testDir, "topLevelOrigin"_ns,
"https://evil.web.megacorp.co.uk^privateBrowsingId=1"_ns);
EXPECT_TRUE(NS_SUCCEEDED(rv));
bool result = MatchBaseDomain(testDir, "longer-example.com"_ns);
EXPECT_FALSE(result);
testDir->Remove(true);
}
TEST(GeckoMediaPlugins, CDMStorageGetNodeId)
{
RefPtr<CDMStorageTest> runner = new CDMStorageTest();
@ -1031,6 +1284,21 @@ TEST(GeckoMediaPlugins, CDMStorageForgetThisSite)
runner->DoTest(&CDMStorageTest::TestForgetThisSite);
}
TEST(GeckoMediaPlugins, CDMStorageForgetThisBaseDomain)
{
RefPtr<CDMStorageTest> runner = new CDMStorageTest();
runner->DoTest(&CDMStorageTest::TestForgetThisBaseDomain);
}
TEST(GeckoMediaPlugins, MatchBaseDomain_MatchOrigin)
{ TestMatchBaseDomain_MatchOrigin(); }
TEST(GeckoMediaPlugins, MatchBaseDomain_MatchTLD)
{ TestMatchBaseDomain_MatchTLD(); }
TEST(GeckoMediaPlugins, MatchBaseDomain_NoMatch)
{ TestMatchBaseDomain_NoMatch(); }
TEST(GeckoMediaPlugins, CDMStorageClearRecentHistory1)
{
RefPtr<CDMStorageTest> runner = new CDMStorageTest();

Просмотреть файл

@ -1188,23 +1188,22 @@ const SecuritySettingsCleaner = {
};
const EMECleaner = {
deleteByHost(aHost, aOriginAttributes) {
return new Promise(aResolve => {
let mps = Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(
Ci.mozIGeckoMediaPluginChromeService
);
mps.forgetThisSite(aHost, JSON.stringify(aOriginAttributes));
aResolve();
});
async deleteByHost(aHost, aOriginAttributes) {
let mps = Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(
Ci.mozIGeckoMediaPluginChromeService
);
mps.forgetThisSite(aHost, JSON.stringify(aOriginAttributes));
},
deleteByPrincipal(aPrincipal) {
return this.deleteByHost(aPrincipal.host, aPrincipal.originAttributes);
},
deleteByBaseDomain(aBaseDomain) {
// TODO: Bug 1705034
return this.deleteByHost(aBaseDomain, {});
async deleteByBaseDomain(aBaseDomain) {
let mps = Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(
Ci.mozIGeckoMediaPluginChromeService
);
mps.forgetThisBaseDomain(aBaseDomain);
},
deleteAll() {