Bug 1646553 - Rework MediaKeys to be fission friendly. r=kmag

This patch reworks how the MediaKeys does 2 things:
1. Listens for documents becoming inactive. Mediakeys will no longer listen
on the top document in the process, and will now instead listen to their own
document.
2. Obtains the top level principal used to create the media keys. Instead of
grabbing the principal from the top document, the MediaKeys will now use their
document's channel's LoadInfo and query the principal from that.

1 will change how the keys behave in iframes -- keys will now shutdown if their
iframe doc becomes inactive, rather than the top in process document. This is
likely to only matter in very niche cases as EME is almost always used in a top
level context.

2 seeks to retain the previous behaviour, but does so in a fission compatible
way.

Differential Revision: https://phabricator.services.mozilla.com/D87788
This commit is contained in:
Bryce Seager van Dyk 2020-08-25 18:03:48 +00:00
Родитель 7f6d4f154e
Коммит 1a16e898b2
1 изменённых файлов: 27 добавлений и 14 удалений

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

@ -408,25 +408,39 @@ already_AddRefed<DetailedPromise> MediaKeys::Init(ErrorResult& aRv) {
}
mPrincipal = sop->GetPrincipal();
// Determine principal of the "top-level" window; the principal of the
// page that will display in the URL bar.
nsCOMPtr<nsPIDOMWindowInner> window = GetParentObject();
if (!window) {
promise->MaybeRejectWithInvalidStateError(
"Couldn't get top-level window in MediaKeys::Init");
return promise.forget();
}
nsCOMPtr<nsPIDOMWindowOuter> top =
window->GetOuterWindow()->GetInProcessTop();
if (!top || !top->GetExtantDoc()) {
mDocument = window->GetExtantDoc();
if (!mDocument) {
NS_WARNING("Failed to get document when creating MediaKeys");
promise->MaybeRejectWithInvalidStateError(
"Couldn't get document in MediaKeys::Init");
return promise.forget();
}
mDocument = top->GetExtantDoc();
// Get the top-level principal so we can partition the GMP based on
// the current + top level principal.
nsIChannel* channel = mDocument->GetChannel();
if (!channel) {
NS_WARNING("Failed to get channel when creating MediaKeys");
promise->MaybeRejectWithInvalidStateError(
"Couldn't get channel in MediaKeys::Init");
return promise.forget();
}
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
MOZ_RELEASE_ASSERT(loadInfo, "Channels should always have LoadInfo");
mTopLevelPrincipal = mDocument->NodePrincipal();
if (loadInfo->GetIsTopLevelLoad()) {
// We're in a top level context so our principal is already top level.
mTopLevelPrincipal = mPrincipal;
} else {
mTopLevelPrincipal = loadInfo->GetTopLevelPrincipal();
if (!mTopLevelPrincipal) {
NS_WARNING("Failed to get top level principal when creating MediaKeys");
promise->MaybeRejectWithInvalidStateError(
"Couldn't get top level principal in MediaKeys::Init");
return promise.forget();
}
}
if (!mPrincipal || !mTopLevelPrincipal) {
NS_WARNING("Failed to get principals when creating MediaKeys");
@ -453,8 +467,7 @@ already_AddRefed<DetailedPromise> MediaKeys::Init(ErrorResult& aRv) {
EME_LOG("MediaKeys[%p]::Create() (%s, %s)", this, origin.get(),
topLevelOrigin.get());
mProxy =
CreateCDMProxy(top->GetExtantDoc()->EventTargetFor(TaskCategory::Other));
mProxy = CreateCDMProxy(mDocument->EventTargetFor(TaskCategory::Other));
// The CDMProxy's initialization is asynchronous. The MediaKeys is
// refcounted, and its instance is returned to JS by promise once