/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BackgroundVideoDecodingPermissionObserver.h" #include "mozilla/AsyncEventDispatcher.h" #include "mozilla/dom/BrowsingContext.h" #include "mozilla/StaticPrefs_media.h" #include "MediaDecoder.h" #include "nsContentUtils.h" #include "mozilla/dom/Document.h" namespace mozilla { BackgroundVideoDecodingPermissionObserver:: BackgroundVideoDecodingPermissionObserver(MediaDecoder* aDecoder) : mDecoder(aDecoder), mIsRegisteredForEvent(false) { MOZ_ASSERT(mDecoder); } NS_IMETHODIMP BackgroundVideoDecodingPermissionObserver::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { if (!StaticPrefs::media_resume_bkgnd_video_on_tabhover()) { return NS_OK; } if (!IsValidEventSender(aSubject)) { return NS_OK; } if (strcmp(aTopic, "unselected-tab-hover") == 0) { bool allowed = !NS_strcmp(aData, u"true"); mDecoder->SetIsBackgroundVideoDecodingAllowed(allowed); } return NS_OK; } void BackgroundVideoDecodingPermissionObserver::RegisterEvent() { MOZ_ASSERT(!mIsRegisteredForEvent); nsCOMPtr observerService = services::GetObserverService(); if (observerService) { observerService->AddObserver(this, "unselected-tab-hover", false); mIsRegisteredForEvent = true; if (nsContentUtils::IsInStableOrMetaStableState()) { // Events shall not be fired synchronously to prevent anything visible // from the scripts while we are in stable state. if (nsCOMPtr doc = GetOwnerDoc()) { doc->Dispatch( TaskCategory::Other, NewRunnableMethod( "BackgroundVideoDecodingPermissionObserver::" "EnableEvent", this, &BackgroundVideoDecodingPermissionObserver::EnableEvent)); } } else { EnableEvent(); } } } void BackgroundVideoDecodingPermissionObserver::UnregisterEvent() { MOZ_ASSERT(mIsRegisteredForEvent); nsCOMPtr observerService = services::GetObserverService(); if (observerService) { observerService->RemoveObserver(this, "unselected-tab-hover"); mIsRegisteredForEvent = false; mDecoder->SetIsBackgroundVideoDecodingAllowed(false); if (nsContentUtils::IsInStableOrMetaStableState()) { // Events shall not be fired synchronously to prevent anything visible // from the scripts while we are in stable state. if (nsCOMPtr doc = GetOwnerDoc()) { doc->Dispatch( TaskCategory::Other, NewRunnableMethod( "BackgroundVideoDecodingPermissionObserver::" "DisableEvent", this, &BackgroundVideoDecodingPermissionObserver::DisableEvent)); } } else { DisableEvent(); } } } BackgroundVideoDecodingPermissionObserver:: ~BackgroundVideoDecodingPermissionObserver() { MOZ_ASSERT(!mIsRegisteredForEvent); } void BackgroundVideoDecodingPermissionObserver::EnableEvent() const { // If we can't get document or outer window, then you can't reach the chrome // either, so we don't need want to dispatch the event. dom::Document* doc = GetOwnerDoc(); if (!doc || !doc->GetWindow()) { return; } RefPtr asyncDispatcher = new AsyncEventDispatcher(doc, u"UnselectedTabHover:Enable"_ns, CanBubble::eYes, ChromeOnlyDispatch::eYes); asyncDispatcher->PostDOMEvent(); } void BackgroundVideoDecodingPermissionObserver::DisableEvent() const { // If we can't get document or outer window, then you can't reach the chrome // either, so we don't need want to dispatch the event. dom::Document* doc = GetOwnerDoc(); if (!doc || !doc->GetWindow()) { return; } RefPtr asyncDispatcher = new AsyncEventDispatcher(doc, u"UnselectedTabHover:Disable"_ns, CanBubble::eYes, ChromeOnlyDispatch::eYes); asyncDispatcher->PostDOMEvent(); } dom::BrowsingContext* BackgroundVideoDecodingPermissionObserver::GetOwnerBC() const { dom::Document* doc = GetOwnerDoc(); return doc ? doc->GetBrowsingContext() : nullptr; } dom::Document* BackgroundVideoDecodingPermissionObserver::GetOwnerDoc() const { if (!mDecoder->GetOwner()) { return nullptr; } return mDecoder->GetOwner()->GetDocument(); } bool BackgroundVideoDecodingPermissionObserver::IsValidEventSender( nsISupports* aSubject) const { nsCOMPtr senderInner(do_QueryInterface(aSubject)); if (!senderInner) { return false; } RefPtr senderBC = senderInner->GetBrowsingContext(); if (!senderBC) { return false; } // Valid sender should be in the same browsing context tree as where owner is. return GetOwnerBC() ? GetOwnerBC()->Top() == senderBC->Top() : false; } NS_IMPL_ISUPPORTS(BackgroundVideoDecodingPermissionObserver, nsIObserver) } // namespace mozilla