Bug 1317927 - Media caching needs to use origin attributes, r=cpearce, r=jesup

This commit is contained in:
Andrea Marchesini 2016-12-07 07:07:09 -10:00
Родитель 98798d9c07
Коммит f7f5990527
22 изменённых файлов: 76 добавлений и 88 удалений

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

@ -351,6 +351,19 @@ OriginAttributes::IsFirstPartyEnabled()
return sFirstPartyIsolation;
}
/* static */
bool
OriginAttributes::IsPrivateBrowsing(const nsACString& aOrigin)
{
nsAutoCString dummy;
PrincipalOriginAttributes attrs;
if (NS_WARN_IF(!attrs.PopulateFromOrigin(aOrigin, dummy))) {
return false;
}
return !!attrs.mPrivateBrowsingId;
}
BasePrincipal::BasePrincipal()
{}

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

@ -68,6 +68,10 @@ public:
// check if "privacy.firstparty.isolate" is enabled.
static bool IsFirstPartyEnabled();
// returns true if the originAttributes suffix has mPrivateBrowsingId value
// different than 0.
static bool IsPrivateBrowsing(const nsACString& aOrigin);
protected:
OriginAttributes() {}
explicit OriginAttributes(const OriginAttributesDictionary& aOther)

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

@ -1230,10 +1230,10 @@ public:
// We won't need mOnFailure now.
mOnFailure = nullptr;
if (!MediaManager::IsPrivateBrowsing(window)) {
if (!OriginAttributes::IsPrivateBrowsing(mOrigin)) {
// Call GetOriginKey again, this time w/persist = true, to promote
// deviceIds to persistent, in case they're not already. Fire'n'forget.
RefPtr<Pledge<nsCString>> p = media::GetOriginKey(mOrigin, false, true);
RefPtr<Pledge<nsCString>> p = media::GetOriginKey(mOrigin, true);
}
return NS_OK;
}
@ -1934,13 +1934,6 @@ MediaManager::NotifyRecordingStatusChange(nsPIDOMWindowInner* aWindow,
return NS_OK;
}
bool MediaManager::IsPrivateBrowsing(nsPIDOMWindowInner* window)
{
nsCOMPtr<nsIDocument> doc = window->GetDoc();
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
return loadContext && loadContext->UsePrivateBrowsing();
}
int MediaManager::AddDeviceChangeCallback(DeviceChangeCallback* aCallback)
{
bool fakeDeviceChangeEventOn = mPrefs.mFakeDeviceChangeEventOn;
@ -2497,7 +2490,6 @@ MediaManager::EnumerateDevicesImpl(uint64_t aWindowId,
// 2. Get the raw devices list
// 3. Anonymize the raw list with the origin-key.
bool privateBrowsing = IsPrivateBrowsing(window);
nsCOMPtr<nsIPrincipal> principal =
nsGlobalWindow::Cast(window)->GetPrincipal();
MOZ_ASSERT(principal);
@ -2512,8 +2504,7 @@ MediaManager::EnumerateDevicesImpl(uint64_t aWindowId,
// thread later once GetOriginKey resolves. Needed variables are "captured"
// (passed by value) safely into the lambda.
RefPtr<Pledge<nsCString>> p = media::GetOriginKey(origin, privateBrowsing,
persist);
RefPtr<Pledge<nsCString>> p = media::GetOriginKey(origin, persist);
p->Then([id, aWindowId, aVideoType, aAudioType,
aFake](const nsCString& aOriginKey) mutable {
MOZ_ASSERT(NS_IsMainThread());

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

@ -257,7 +257,6 @@ public:
MediaEnginePrefs mPrefs;
typedef nsTArray<RefPtr<MediaDevice>> SourceSet;
static bool IsPrivateBrowsing(nsPIDOMWindowInner* window);
virtual int AddDeviceChangeCallback(DeviceChangeCallback* aCallback) override;
virtual void OnDeviceChange() override;

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

@ -95,8 +95,7 @@ public:
virtual void Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aName,
bool aInPrivateBrowsing) = 0;
const nsAString& aName) = 0;
virtual void OnSetDecryptorId(uint32_t aId) {}

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

@ -409,14 +409,10 @@ MediaKeys::Init(ErrorResult& aRv)
return promise.forget();
}
nsIDocument* doc = window->GetExtantDoc();
const bool inPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);
EME_LOG("MediaKeys[%p]::Create() (%s, %s), %s",
EME_LOG("MediaKeys[%p]::Create() (%s, %s)",
this,
origin.get(),
topLevelOrigin.get(),
(inPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
topLevelOrigin.get());
// The CDMProxy's initialization is asynchronous. The MediaKeys is
// refcounted, and its instance is returned to JS by promise once
@ -432,8 +428,7 @@ MediaKeys::Init(ErrorResult& aRv)
mProxy->Init(mCreatePromiseId,
NS_ConvertUTF8toUTF16(origin),
NS_ConvertUTF8toUTF16(topLevelOrigin),
KeySystemToGMPName(mKeySystem),
inPrivateBrowsing);
KeySystemToGMPName(mKeySystem));
return promise.forget();
}

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

@ -46,16 +46,14 @@ void
MediaDrmCDMProxy::Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aName,
bool aInPrivateBrowsing)
const nsAString& aName)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
EME_LOG("MediaDrmCDMProxy::Init (%s, %s) %s",
NS_ConvertUTF16toUTF8(aOrigin).get(),
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
(aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get());
// Create a thread to work with cdm.
if (!mOwnerThread) {

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

@ -37,8 +37,7 @@ public:
void Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing) override;
const nsAString& aGMPName) override;
void CreateSession(uint32_t aCreateSessionToken,
MediaKeySessionType aSessionType,

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

@ -54,16 +54,14 @@ void
GMPCDMProxy::Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing)
const nsAString& aGMPName)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
EME_LOG("GMPCDMProxy::Init (%s, %s) %s",
EME_LOG("GMPCDMProxy::Init (%s, %s)",
NS_ConvertUTF16toUTF8(aOrigin).get(),
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
(aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get());
nsCString pluginVersion;
if (!mOwnerThread) {
@ -93,7 +91,6 @@ GMPCDMProxy::Init(PromiseId aPromiseId,
data->mOrigin = aOrigin;
data->mTopLevelOrigin = aTopLevelOrigin;
data->mGMPName = aGMPName;
data->mInPrivateBrowsing = aInPrivateBrowsing;
data->mCrashHelper = mCrashHelper;
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<UniquePtr<InitData>&&>(this,
@ -210,7 +207,6 @@ GMPCDMProxy::gmp_Init(UniquePtr<InitData>&& aData)
nsresult rv = mps->GetNodeId(data.mOrigin,
data.mTopLevelOrigin,
data.mGMPName,
data.mInPrivateBrowsing,
Move(callback));
if (NS_FAILED(rv)) {
RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
@ -241,10 +237,9 @@ GMPCDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
return;
}
EME_LOG("GMPCDMProxy::gmp_Init (%s, %s) %s NodeId=%s",
EME_LOG("GMPCDMProxy::gmp_Init (%s, %s) NodeId=%s",
NS_ConvertUTF16toUTF8(aData->mOrigin).get(),
NS_ConvertUTF16toUTF8(aData->mTopLevelOrigin).get(),
(aData->mInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"),
GetNodeId().get());
nsTArray<nsCString> tags;

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

@ -31,8 +31,7 @@ public:
void Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing) override;
const nsAString& aGMPName) override;
void OnSetDecryptorId(uint32_t aId) override;
@ -123,7 +122,6 @@ private:
nsString mTopLevelOrigin;
nsString mGMPName;
RefPtr<GMPCrashHelper> mCrashHelper;
bool mInPrivateBrowsing;
};
// GMP thread only.

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

@ -235,7 +235,6 @@ NS_IMETHODIMP
GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing,
UniquePtr<GetNodeIdCallback>&& aCallback)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
@ -245,14 +244,12 @@ GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
nsString origin(aOrigin);
nsString topLevelOrigin(aTopLevelOrigin);
nsString gmpName(aGMPName);
bool pb = aInPrivateBrowsing;
GetServiceChild()->Then(thread, __func__,
[rawCallback, origin, topLevelOrigin, gmpName, pb](GMPServiceChild* child) {
[rawCallback, origin, topLevelOrigin, gmpName](GMPServiceChild* child) {
UniquePtr<GetNodeIdCallback> callback(rawCallback);
nsCString outId;
if (!child->SendGetGMPNodeId(origin, topLevelOrigin,
gmpName,
pb, &outId)) {
gmpName, &outId)) {
callback->Done(NS_ERROR_FAILURE, EmptyCString());
return;
}

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

@ -32,7 +32,6 @@ public:
NS_IMETHOD GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsingMode,
UniquePtr<GetNodeIdCallback>&& aCallback) override;
NS_DECL_NSIOBSERVER

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

@ -1388,14 +1388,12 @@ nsresult
GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing,
nsACString& aOutId)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
LOGD(("%s::%s: (%s, %s), %s", __CLASS__, __FUNCTION__,
LOGD(("%s::%s: (%s, %s)", __CLASS__, __FUNCTION__,
NS_ConvertUTF16toUTF8(aOrigin).get(),
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
(aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")));
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get()));
nsresult rv;
@ -1421,7 +1419,7 @@ GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
const uint32_t hash = AddToHash(HashString(aOrigin),
HashString(aTopLevelOrigin));
if (aInPrivateBrowsing) {
if (OriginAttributes::IsPrivateBrowsing(NS_ConvertUTF16toUTF8(aOrigin))) {
// For PB mode, we store the node id, indexed by the origin pair and GMP name,
// so that if the same origin pair is opened for the same GMP in this session,
// it gets the same node id.
@ -1551,11 +1549,10 @@ NS_IMETHODIMP
GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing,
UniquePtr<GetNodeIdCallback>&& aCallback)
{
nsCString nodeId;
nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aGMPName, aInPrivateBrowsing, nodeId);
nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aGMPName, nodeId);
aCallback->Done(rv, nodeId);
return rv;
}
@ -2010,11 +2007,9 @@ mozilla::ipc::IPCResult
GMPServiceParent::RecvGetGMPNodeId(const nsString& aOrigin,
const nsString& aTopLevelOrigin,
const nsString& aGMPName,
const bool& aInPrivateBrowsing,
nsCString* aID)
{
nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin, aGMPName,
aInPrivateBrowsing, *aID);
nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin, aGMPName, *aID);
if (!NS_SUCCEEDED(rv)) {
return IPC_FAIL_NO_REASON(this);
}

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

@ -44,7 +44,6 @@ public:
NS_IMETHOD GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsingMode,
UniquePtr<GetNodeIdCallback>&& aCallback) override;
NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE
@ -90,8 +89,7 @@ private:
size_t* aOutPluginIndex);
nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing, nsACString& aOutId);
const nsAString& aGMPName, nsACString& aOutId);
void UnloadPlugins();
void CrashPlugins();
@ -250,7 +248,6 @@ public:
mozilla::ipc::IPCResult RecvGetGMPNodeId(const nsString& aOrigin,
const nsString& aTopLevelOrigin,
const nsString& aGMPName,
const bool& aInPrivateBrowsing,
nsCString* aID) override;
void ActorDestroy(ActorDestroyReason aWhy) override;

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

@ -22,9 +22,7 @@ parent:
ProcessId[] alreadyBridgedTo)
returns (uint32_t pluginId, ProcessId id, nsCString displayName, nsresult aResult);
sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
nsString gmpName,
bool inPrivateBrowsing)
sync GetGMPNodeId(nsString origin, nsString topLevelOrigin, nsString gmpName)
returns (nsCString id);
};

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

@ -161,12 +161,11 @@ interface mozIGeckoMediaPluginService : nsISupports
in GetGMPDecryptorCallback callback);
/**
* Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
* Gets the NodeId for a (origin, urlbarOrigin) pair.
*/
[noscript]
void getNodeId(in AString origin,
in AString topLevelOrigin,
in AString gmpName,
in bool inPrivateBrowsingMode,
in GetNodeIdCallback callback);
};

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

@ -473,12 +473,26 @@ GetNodeId(const nsAString& aOrigin,
nsresult result;
UniquePtr<GetNodeIdCallback> callback(new TestGetNodeIdCallback(nodeId,
result));
PrincipalOriginAttributes attrs;
attrs.mPrivateBrowsingId = aInPBMode ? 1 : 0;
nsAutoCString suffix;
attrs.CreateSuffix(suffix);
nsAutoString origin;
origin.Assign(aOrigin);
origin.Append(NS_ConvertUTF8toUTF16(suffix));
nsAutoString topLevelOrigin;
topLevelOrigin.Assign(aTopLevelOrigin);
topLevelOrigin.Append(NS_ConvertUTF8toUTF16(suffix));
// We rely on the fact that the GetNodeId implementation for
// GeckoMediaPluginServiceParent is synchronous.
nsresult rv = service->GetNodeId(aOrigin,
aTopLevelOrigin,
nsresult rv = service->GetNodeId(origin,
topLevelOrigin,
NS_LITERAL_STRING("gmp-fake"),
aInPBMode,
Move(callback));
EXPECT_TRUE(NS_SUCCEEDED(rv) && NS_SUCCEEDED(result));
return nodeId;

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

@ -20,7 +20,7 @@ namespace mozilla {
namespace media {
already_AddRefed<Pledge<nsCString>>
GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing, bool aPersist)
GetOriginKey(const nsCString& aOrigin, bool aPersist)
{
RefPtr<MediaManager> mgr = MediaManager::GetInstance();
MOZ_ASSERT(mgr);
@ -29,10 +29,9 @@ GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing, bool aPersist)
uint32_t id = mgr->mGetOriginKeyPledges.Append(*p);
if (XRE_GetProcessType() == GeckoProcessType_Default) {
mgr->GetNonE10sParent()->RecvGetOriginKey(id, aOrigin, aPrivateBrowsing,
aPersist);
mgr->GetNonE10sParent()->RecvGetOriginKey(id, aOrigin, aPersist);
} else {
Child::Get()->SendGetOriginKey(id, aOrigin, aPrivateBrowsing, aPersist);
Child::Get()->SendGetOriginKey(id, aOrigin, aPersist);
}
return p.forget();
}

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

@ -25,7 +25,7 @@ namespace media {
// (promise-like objects) with the future value. Use pledge.Then(func) to access.
already_AddRefed<Pledge<nsCString>>
GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing, bool aPersist);
GetOriginKey(const nsCString& aOrigin, bool aPersist);
void
SanitizeOriginKeys(const uint64_t& aSinceWhen, bool aOnlyPrivateBrowsing);

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

@ -369,7 +369,6 @@ bool NonE10s::SendGetOriginKeyResponse(const uint32_t& aRequestId,
template<class Super> mozilla::ipc::IPCResult
Parent<Super>::RecvGetOriginKey(const uint32_t& aRequestId,
const nsCString& aOrigin,
const bool& aPrivateBrowsing,
const bool& aPersist)
{
MOZ_ASSERT(NS_IsMainThread());
@ -395,11 +394,12 @@ Parent<Super>::RecvGetOriginKey(const uint32_t& aRequestId,
RefPtr<Parent<Super>> that(this);
rv = sts->Dispatch(NewRunnableFrom([this, that, id, profileDir, aOrigin,
aPrivateBrowsing, aPersist]() -> nsresult {
aPersist]() -> nsresult {
MOZ_ASSERT(!NS_IsMainThread());
mOriginKeyStore->mOriginKeys.SetProfileDir(profileDir);
nsCString result;
if (aPrivateBrowsing) {
nsAutoCString result;
if (OriginAttributes::IsPrivateBrowsing(aOrigin)) {
mOriginKeyStore->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result);
} else {
mOriginKeyStore->mOriginKeys.GetOriginKey(aOrigin, result, aPersist);

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

@ -29,7 +29,6 @@ public:
protected:
virtual mozilla::ipc::IPCResult RecvGetOriginKey(const uint32_t& aRequestId,
const nsCString& aOrigin,
const bool& aPrivateBrowsing,
const bool& aPersist) = 0;
virtual mozilla::ipc::IPCResult RecvSanitizeOriginKeys(const uint64_t& aSinceWhen,
const bool& aOnlyPrivateBrowsing) = 0;
@ -52,7 +51,6 @@ public:
virtual mozilla::ipc::IPCResult RecvGetOriginKey(const uint32_t& aRequestId,
const nsCString& aOrigin,
const bool& aPrivateBrowsing,
const bool& aPersist) override;
virtual mozilla::ipc::IPCResult RecvSanitizeOriginKeys(const uint64_t& aSinceWhen,
const bool& aOnlyPrivateBrowsing) override;

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

@ -18,18 +18,19 @@ parent:
* This is needed by mediaDevices.enumerateDevices() to produce persistent
* deviceIds that wont work cross-origin.
*
* If aPrivateBrowsing is false, a key for this origin is returned from a
* primary pool of temporal in-memory keys and persistent keys read from disk.
* If no key exists, a temporal one is created.
* The origin string must contain the OriginAttributes suffix.
* If this OriginAttributes dictionary has the privateBrowsing flag set to
* false, a key for this origin is returned from a primary pool of temporal
* in-memory keys and persistent keys read from disk. If no key exists, a
* temporal one is created.
* If aPersist is true and key is temporal, the key is promoted to persistent.
* Once persistent, a key cannot become temporal again.
*
* If aPrivateBrowsing is true, a different key for this origin is returned
* from a secondary pool that is never persisted to disk, and aPersist is
* ignored.
* If the OriginAttributes dictionary has the privateBrowsing flag set to
* true, a different key for this origin is returned from a secondary pool
* that is never persisted to disk, and aPersist is ignored.
*/
async GetOriginKey(uint32_t aRequestId, nsCString aOrigin, bool aPrivateBrowsing,
bool aPersist);
async GetOriginKey(uint32_t aRequestId, nsCString aOrigin, bool aPersist);
/**
* Clear per-orgin list of persistent deviceIds stored for enumerateDevices