Bug 1274919 - Part 2: Start decoding suspended video when mouse begins hovering tab. r?cpearce
MozReview-Commit-ID: 80SGYdE1atj
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4039,17 +4039,21 @@ nsPIDOMWindowOuter::SetTabHovered(bool a
#endif
if (mTabHovered == aHovered) {
return;
}
mTabHovered = aHovered;
- // TODO: Notify media elements to become ready (exit suspend/dormant, spin
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (obs) {
+ obs->NotifyObservers(ToSupports(this), "tab-hover",
+ mTabHovered ? MOZ_UTF16("true") : MOZ_UTF16("false"));
+ }
}
bool
nsPIDOMWindowInner::GetAudioCaptured() const
{
MOZ_ASSERT(IsInnerWindow());
return mAudioCaptured;
}
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4576,43 +4576,88 @@ void HTMLMediaElement::AddRemoveSelfRefe
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING));
if (needSelfReference != mHasSelfReference) {
mHasSelfReference = needSelfReference;
if (needSelfReference) {
// The observer service will hold a strong reference to us. This
// will do to keep us alive. We need to know about shutdown so that
// we can release our self-reference.
- nsContentUtils::RegisterShutdownObserver(this);
+ RegisterObservers();
} else {
// Dispatch Release asynchronously so that we don't destroy this object
// inside a call stack of method calls on this object
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod(this, &HTMLMediaElement::DoRemoveSelfReference);
NS_DispatchToMainThread(event);
}
}
UpdateAudioChannelPlayingState();
}
void HTMLMediaElement::DoRemoveSelfReference()
{
// We don't need the shutdown observer anymore. Unregistering releases
// its reference to us, which we were using as our self-reference.
+ UnregisterObservers();
+}
+
+void HTMLMediaElement::RegisterObservers()
+{
+ nsContentUtils::RegisterShutdownObserver(this);
+
+ // Register interest in tab-hover. This is used to notify decoders to wake up
+ // from suspended state.
+ nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+ if (observerService) {
+ observerService->AddObserver(this, "tab-hover", false);
+ }
+}
+
+void HTMLMediaElement::UnregisterObservers()
+{
nsContentUtils::UnregisterShutdownObserver(this);
+
+ nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+ if (observerService) {
+ observerService->RemoveObserver(this, "tab-hover");
+ }
}
nsresult HTMLMediaElement::Observe(nsISupports* aSubject,
- const char* aTopic, const char16_t* aData)
+ const char* aTopic,
+ const char16_t* aData)
{
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
mShuttingDown = true;
AddRemoveSelfReference();
- }
+ } else if (strcmp(aTopic, "tab-hover") == 0) {
+ nsIDocument* doc = OwnerDoc();
+ if (!doc) {
+ return NS_OK;
+ }
+
+ nsPIDOMWindowOuter* owningWindow = doc->GetWindow();
+ nsCOMPtr<nsPIDOMWindowOuter> sourceWindow = do_QueryInterface(aSubject);
+ if (!owningWindow || owningWindow != sourceWindow) {
+ return NS_OK;
+ }
+
+ nsAutoString value(aData);
+ bool tabHovered = value.EqualsASCII("true");
+
+ // Tell the decoder that it needs to wake up.
+ // TODO: At the moment this is done via tell the decoder that it has
+ // become visible. This may need to change.
+ if (mDecoder && !IsBeingDestroyed()) {
+ mDecoder->NotifyOwnerActivityChanged(tabHovered || !IsHidden());
+ }
+ }
+
return NS_OK;
}
bool
HTMLMediaElement::IsNodeOfType(uint32_t aFlags) const
{
return !(aFlags & ~(eCONTENT | eMEDIA));
}
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -981,16 +981,19 @@ protected:
*/
void AddRemoveSelfReference();
/**
* Called asynchronously to release a self-reference to this element.
*/
void DoRemoveSelfReference();
+ void RegisterObservers();
+ void UnregisterObservers();
+
/**
* Possible values of the 'preload' attribute.
*/
enum PreloadAttrValue {
PRELOAD_ATTR_EMPTY, // set to ""
PRELOAD_ATTR_NONE, // set to "none"
PRELOAD_ATTR_METADATA, // set to "metadata"
PRELOAD_ATTR_AUTO // set to "auto"