Bug 1342883 - part1: When nsDocument receive unload event from nsDocumentViewer, nofity the MediaElements. r=smaug
MozReview-Commit-ID: PZZAAjHYgL
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -4913,37 +4913,46 @@ nsDocument::ContainsMSEContent()
{
bool containsMSE = false;
EnumerateActivityObservers(CheckIfContainsMSEContent,
static_cast<void*>(&containsMSE));
return containsMSE;
}
static void
-NotifyActivityChanged(nsISupports *aSupports, void *aUnused)
+NotifyActivityChanged(nsISupports *aSupports, void *aDocumentUnload)
{
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aSupports));
if (domMediaElem) {
nsCOMPtr<nsIContent> content(do_QueryInterface(domMediaElem));
MOZ_ASSERT(content, "aSupports is not a content");
HTMLMediaElement* mediaElem = static_cast<HTMLMediaElement*>(content.get());
- mediaElem->NotifyOwnerDocumentActivityChanged();
+ bool unload = static_cast<bool*>(aDocumentUnload) ?
+ *static_cast<bool*>(aDocumentUnload) : false;
+ mediaElem->NotifyOwnerDocumentActivityChanged(&unload);
}
nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aSupports));
if (objectLoadingContent) {
nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
olc->NotifyOwnerDocumentActivityChanged();
}
nsCOMPtr<nsIDocumentActivity> objectDocumentActivity(do_QueryInterface(aSupports));
if (objectDocumentActivity) {
objectDocumentActivity->NotifyOwnerDocumentActivityChanged();
}
}
void
+nsDocument::NotifyUnloadEvent()
+{
+ bool unload = true;
+ EnumerateActivityObservers(NotifyActivityChanged, (void*)&unload);
+}
+
+void
nsIDocument::SetContainer(nsDocShell* aContainer)
{
if (aContainer) {
mDocumentContainer = aContainer;
} else {
mDocumentContainer = WeakPtr<nsDocShell>();
}
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -656,17 +656,17 @@ public:
virtual void NotifyIntersectionObservers() override;
virtual void NotifyLayerManagerRecreated() override;
virtual void ScheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG) override;
virtual void UnscheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG) override;
virtual void ResolveScheduledSVGPresAttrs() override;
bool IsSynthesized();
-
+ virtual void NotifyUnloadEvent() override;
private:
void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
public:
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -1087,16 +1087,17 @@ public:
*/
virtual void ScheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG) = 0;
// Unschedule an element scheduled by ScheduleFrameRequestCallback (e.g. for when it is destroyed)
virtual void UnscheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG) = 0;
// Resolve all SVG pres attrs scheduled in ScheduleSVGForPresAttrEvaluation
virtual void ResolveScheduledSVGPresAttrs() = 0;
+ virtual void NotifyUnloadEvent() {};
protected:
virtual Element *GetRootElementInternal() const = 0;
void SetPageUnloadingEventTimeStamp()
{
MOZ_ASSERT(!mPageUnloadingEventTimeStamp);
mPageUnloadingEventTimeStamp = mozilla::TimeStamp::NowLoRes();
}
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -6337,17 +6337,17 @@ bool HTMLMediaElement::IsBeingDestroyed(
nsIDocShell* docShell = ownerDoc ? ownerDoc->GetDocShell() : nullptr;
bool isBeingDestroyed = false;
if (docShell) {
docShell->IsBeingDestroyed(&isBeingDestroyed);
}
return isBeingDestroyed;
}
-void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
+void HTMLMediaElement::NotifyOwnerDocumentActivityChanged(bool aDocumentUnload)
{
bool visible = !IsHidden();
if (visible) {
// Visible -> Just pause hidden play time (no-op if already paused).
HiddenVideoStop();
} else if (mPlayTime.IsStarted()) {
// Not visible, play time is running -> Start hidden play time if needed.
HiddenVideoStart();
@@ -6357,22 +6357,26 @@ void HTMLMediaElement::NotifyOwnerDocume
NotifyDecoderActivityChanges();
}
bool pauseElement = ShouldElementBePaused();
SuspendOrResumeElement(pauseElement, !IsActive());
// If the owning document has become inactive we should shutdown the CDM.
if (!OwnerDoc()->IsCurrentActiveDocument() && mMediaKeys) {
- mMediaKeys->Shutdown();
- mMediaKeys = nullptr;
- if (mDecoder) {
- ShutdownDecoder();
- }
- }
+ mMediaKeys->Shutdown();
+ mMediaKeys = nullptr;
+ if (mDecoder) {
+ ShutdownDecoder();
+ }
+ }
+
+ if (aDocumentUnload && mDecoder) {
+ ShutdownDecoder();
+ }
AddRemoveSelfReference();
}
void HTMLMediaElement::AddRemoveSelfReference()
{
// XXX we could release earlier here in many situations if we examined
// which event listeners are attached. Right now we assume there is a
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -232,17 +232,17 @@ public:
// ImageContainer containing the video data.
virtual VideoFrameContainer* GetVideoFrameContainer() final override;
layers::ImageContainer* GetImageContainer();
/**
* Call this to reevaluate whether we should start/stop due to our owner
* document being active, inactive, visible or hidden.
*/
- void NotifyOwnerDocumentActivityChanged();
+ void NotifyOwnerDocumentActivityChanged(bool aDocumentUnload = false);
// From PrincipalChangeObserver<DOMMediaStream>.
void PrincipalChanged(DOMMediaStream* aStream) override;
void UpdateSrcStreamVideoPrincipal(const PrincipalHandle& aPrincipalHandle);
// Called after the MediaStream we're playing rendered a frame to aContainer
// with a different principalHandle than the previous frame.
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -1423,16 +1423,20 @@ nsDocumentViewer::PageHide(bool aIsUnloa
// Never permit popups from the unload handler, no matter how we get
// here.
nsAutoPopupStatePusher popupStatePusher(openAbused, true);
nsIDocument::PageUnloadingEventTimeStamp timestamp(mDocument);
EventDispatcher::Dispatch(window, mPresContext, &event, nullptr, &status);
+ nsIDocument* doc = GetDocument();
+ if (doc) {
+ doc->NotifyUnloadEvent();
+ }
}
#ifdef MOZ_XUL
// look for open menupopups and close them after the unload event, in case
// the unload event listeners open any new popups
nsContentUtils::HidePopupsInDocument(mDocument);
#endif