Files
palemoon27/dom/html/TextTrackManager.cpp
roytam1 136569692c import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1212148 - Outline DialogValueHolder::Get() and create the variant directly. r=bz (1f3eb24a70)
- Bug 1210591, part 1 - Use nsVariantCC in various places. r=smaug (960ec7f9d3)
- Bug 1210591, part 2 - Cycle collect DataTransfer::mItems. r=smaug (3bc922fd42)
- Bug 931283, part 1 - Rename nsVariant to nsVariantBase. r=froydnj (1ba409004e)
- Bug 931283, part 2 - Split out nsVariant into a subclass. r=froydnj (6fc4012db0)
- Bug 931283, part 3 - Implement a cycle collected version of nsVariant. r=froydnj (9dd0e97d28)
- Bug 1208815 - Use the legacy opt-out in GetMozSourceNode to avoid crashes. r=bholley (b8aaa945fd)
- Bug 1217614 - Remove nsIDOMDataTransfer::mozGetDataAt and refactor associated code. r=bz (6a5a403776)
- Bug 1197002 - Use channel->Open2() in editor/libeditor/nsHTMLDataTransfer.cpp (r=sicking) (4995576e25)
- Bug 1169268 - Don't crash when pasting files. r=ndeakin (b52b5e9971)
- Bug 1156062 part 1b - Convert some callers of nsEditor::SplitNodeDeep; r=ehsan (c0ecbdf8ec)
- Bug 1156062 part 1c - Convert remaining callers of nsEditor::SplitNodeDeep; r=ehsan (e9cb446bef)
- Bug 1156062 part 1d - Clean up nsEditor::SplitNodeDeep; r=ehsan (d8513a605c)
- Bug 1156062 part 2 - Make GetBlockNodeParent and GetEnclosingTable return regular pointers; r=ehsan (8e80c4c53c)
- Bug 1156062 part 3 - New helper nsHTMLEditor::GetBlock; r=ehsan (9466c926f3)
- Bug 1145395 - Call nsINode::Length directly in nsHTMLEditor::CreateDOMFragmentFromPaste; r=ehsan (5b9d9b208c)
- Bug 1152229 Define FnLock as a KeyboardEvent.code value r=smaug (0f0ba16ba2)
- Bug 1192774 - Rename nsOuterWindowProxy::GetWindow to GetOuterWindow and add an assertion; r=khuey (5bbad7f98a)
- Bug 920734 - Part 1: Implement window.orientation and window.onorientationchange. r=baku (3f350de924)
- Bug 920734 - Part 2: Update tests to avoid using orientation as variable name. r=seth (a5c98bcc6f)
- Bug 1216072 - Pass aCallerIsChrome in more places. r=bz Bug 1215398 - Hoist the IsCallerChrome call in CanMoveResizeWindows to the script-only entry points. r=bz (3ff7d3d1a2)
- Bug 1107443. Make WindowProxy throw if you attempt to explicitly define a non-configurable property. r=peterv (d4659731fe)
- Bug 1196317 - Optimize CallbackObject::mCreationStack out from cycle collection graph when possible, r=mccr8 (6221298ec7)
- Bug 1184058 - AudioChannelAgent should be muted when used without a proper window object. r=alwu (3bc66c7727)
- Bug 1196361 - Remove the media.useAudioChannelService pref; r=baku (ba976d4402)
- Bug 1190040 - Part 2: Teach the audio channel service how to not notify audio-playback, and do that when a media element has no audio track; r=padenot (b163cbd6e2)
- Bug 1180940 - Changed return type of AudioDestinationNode::CreateAudioChannelAgent method to return errors, if any methods that it calls fail. Added code to handle the return value in AudioContext::Init(), and its callers. r=baku (03671277dc)
- Bug 1183304 - Unregister the actor when unlinked by CC. r=ehsan (ad0a3a7050)
- Bug 1191814 - WebSpeech synthesis API and AudioChannelService, r=eeejay (2140326485)
- Bug 1043165 - Part 1: Add TelephonyCall.disconnectedReason (webidl). r=hsinyi (a08a2e3b19)
- Bug 1043165 - Part 2: Add TelephonyCall.disconnectedReason (dom). r=hsinyi (1403f942fd)
- Bug 1043165 - Part 3: Add TelephonyCall.disconnectedReason (ril). r=hsinyi (cdb3991ed0)
- Bug 1043165 - Part 4: Update test cases. r=hsinyi (aa3f784b07)
- Bug 1131047 - Part 1: Obsolete some events (WebIDL). r=hsinyi (64e098a773)
- Bug 1131047 - Part 2: Obsolete some events (DOM). r=aknow (75caf5fa03)
- Bug 1161403 - Part 1: Deprecate internal states. r=aknow (dfd955bf8b)
- Bug 1161403 - Part 2: A new testcase. r=aknow (4798f3ec44)
- Bug 1129882 - create agent in telephony object. r=baku, r=hsinyi (1d7e7e44a4)
- Bug 1129882 - add mozInterrupt in telephony object. r=baku (f52465229b)
- Bug 1211511 - AudioChannelAgent::NotifyStartedPlaying and NotifyStoppedPlaying should use the same level of playback notification, r=roc (a73b0fda70)
- Bug 1187204 - AudioChannelService must exist before calling IsAudioChannelMutedByDefault(), r=alwu (665d082d4f)
- Bug 1089526 - Correct function name. r=baku (0706ced01f)
- Bug 1183925 - Part 1: Clean up the SpeakerManagerService shutdown; r=baku (7aefa655d5)
- Bug 1223734 - AudioChannelService should not be re-initialized after the XPCOM shutdown, r=smaug (1e35895d8d)
- Bug 1223734 - Add crashtest. r=baku (cfb753dcf2)
- Bug 1151992 - Use call state to decide the usages of output device. r=baku (37ea21895f)
- Bug 1215684 - Shut down AudioChannelService in the child process. r=mccr8 (389b137630)
- Bug 1183033 - Don't mute the system channel type. r=baku (da88f69119)
- Bug 1218396 - By default window-less AudioChannelAgents should be muted, r=alwu (3a74b6e8e0)
- Bug 1222902 - Create log system for the AudioChannel. r=baku. (4734efd27b)
- var-let (9849b3f3a9)
- Bug 1138354 - Add proxy authencation info for 'mozbrowserusernameandpasswordrequired' event. r=mayhemer (e1717f0113)
- Bug 1195801 - part 2: Tests for getStructuredData. r=kanru (221d9b4fa8)
- Bug 1169633 - [Browser API] getWebManifest(). r=kanru, r=bholley (904c043d16)
- Bug 1206581 - Implement notifyChannel() on AudioChannel API. r=kanru, r=baku. (42554161e7)
- Bug 1196654 - navigator.mozBrowserElementProxy for access Browser API methods from the embedded, r=kanru, sr=sicking (878b701d4b)
- Bug 1214133 - Preload ExtensionContent.jsm to get rid of the overhead. r=fabrice (50f6584735)
- Bug 1212321 - Stop painting on app launch. r=fabrice (a4cadc9577)
- Bug 1203068 - Add system type into kMozAudioChannelAttributeTable. r=baku (c908fef580)
- Bug 1208353 - Fix -Wshadow warnings in dom/audiochannel. r=padenot (85193d75a2)
- Bug 1184970 - Remove unused struct in AudioChannelService, r=ehsan (f0511a942b)
- Bug 1214491 - Rejigger entry points for nsGlobalWindow::Close. r=bz (6eccbffe1f)
- Bug 1212360. Split up the MozStorageChanged event into separate events for sessionstorage and localstorage. r=khuey (ff0047fe22)
- Bug 1162013. Process the Promise queue between adjacent setTimeout callback invocations when we're going through the callback list without returning to the event loop. r=smaug (f4966fa41e)
- Bug 1214491 - Remove CanCallerAccess check for XPIDL version of nsGlobalWindow::AddEventListener. r=bz (5bb993e1ea)
- Bug 1181176 - Pass along x and y position for context menus on Graphene. r=fabrice (652b528a92)
- Bug 1211481 - Expose screenX and screenY to context menu events. r=fabrice (e9679e9d6c)
- Bug 952456 - Part 2: Support copy image in BrowserElement. r=kchen (f91eb8ae95)
- Bug 952456 - Part 3: Enable test_copyimage.html on gonk/cocoa r=fabrice (be0d20fd99)
- Bug 1121463 - Support copy link on context menu. r=kanru (a981b7e05c)
- Backout c7c68c4389d6 (bug 1125713) for gaia app startup regression r=me (ed1d13993f)
- Bug 1178484 - Part 2: Regenerate gecko's in-tree parser. r=hsivone (42d5b50cf1)
- Bug 1164123 - Add support for a theme-group meta to make theme-color"themable". r=fabrice (40757cf461)
- Bug 1178484 - Part 4: Fire metachange event when a <meta> tag has Open Graph data. r=kanru (111cf1c43f)
- Bug 1178484 - Part 5: Test for metachange event when Open Graph property is loaded. r=kanru (0b464de5de)
- Bug 1156615 - (Browser API) ctrl/cmd/middle-click doesn't work if <a> element has children. r=kchen (673a7031f9)
- Bug 1210265 - Add a pref toggle for copying/pasting only plain text on B2G. r=timdream (4fbbad858e)
- Bug 1198522 - Add a flag to make sure customized menu is added. r=timdream, r=kanru (81e611997d)
- Bug 1168658 - Enable tracking protection in b2g r=francois (fc04c160ae)
- Bug 1189494 - Pass tracking information to BrowserElement's mozbrowsersecuritychange event. r=fabrice (bb24e94178)
- Bug 1170644 - Fix forced reflow in BrowserElementChildPreload. r=bz (73078e79fa)
- Bug 1178069 - Check devices capability before enable use of vp8 hardware acceleration using android.media.MediaCodecList and android.media.MediaCodecInfo r=jrmuizel (883351b87c)
- Bug 1164036 - Add an xpcshell test for graphics blocklist versioning. r=kats (c846c5b142)
- Bug 1183725 - Windows 10 not recognized in downloadable blocklist. r=bas (6a07f03ea3)
- Bug 1191404 - Update the comments to avoid confusion about what happens with blocklisting when the OS is unknown. No code change. r=milan (40bec16ce6)
- Bug 1215892 - Fix clang's -Wimplicit-fallthrough warnings in gfx. r=BenWa (83d160740c)
- var/const crashreporter (c9e5ccbb70)
- Bug 1225233 - Make MovableCellHasher a public interface, usable by embedders; r=jonco (603b00a836)
- Bug 1214508: SharedStubs - Part 1: Move the getprop stubs in to shared stub files, r=jandem (7cddae3b9e)
- Bug 1214508: SharedStubs - Part 2: Adjust the getprop stubs to report which engine they use, r=jandem (03ae066cad)
- Bug 1214508: SharedStubs - Part 3: Enable the getprop stubs in ionmonkey, r=jandem (e002db87c2)
- Bug 1214508: SharedStubs - Part 4: Make sure the frame pushed are set correctly for ion vmcalls, r=jandem (6238ed03c4)
- Bug 1214508: SharedStubs - Part 5: Fix ion vmcalls in shared stub, r=jandem (5a914ccfe6)
- Bug 1214508: SharedStubs - Part 6: Move the monitor stubs in to shared stub files, r=jandem (6f03cfaa1f)
- Bug 1214508: SharedStubs - Part 7: Adjust the getprop stubs to report which engine they use, r=jandem (e3849fde89)
- Bug 1214508: SharedStubs - Part 8: Dont sync for the decompiler in ion, r=jandem (7fe1a01bca)
- Bug 1214508: SharedStubs - Fix bustage in arm64, r=bustage on CLOSED TREE (0b60ba5974)
- Bug 1214508: SharedStubs - fix bustage, r=bustage (968a63544d)
- Bug 1212624 - Make WeakMapBase be a LinkedListElement, r=Waldo (744bb6eb8d)
- Bug 1223519 - Remove unused rekeying logic from WeakMap; r=sfink (3a4fe3b5df)
- Bug 1219288 - Ensure module environment object is not extensible and contains only non-configurable properties r=shu (0b9ac212b9)
2023-01-05 23:57:13 +08:00

385 lines
11 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "mozilla/dom/TextTrackManager.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/HTMLTrackElement.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/TextTrack.h"
#include "mozilla/dom/TextTrackCue.h"
#include "mozilla/dom/Event.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsComponentManagerUtils.h"
#include "nsVariant.h"
#include "nsVideoFrame.h"
#include "nsIFrame.h"
#include "nsTArrayHelpers.h"
#include "nsIWebVTTParserWrapper.h"
namespace mozilla {
namespace dom {
CompareTextTracks::CompareTextTracks(HTMLMediaElement* aMediaElement)
{
mMediaElement = aMediaElement;
}
int32_t
CompareTextTracks::TrackChildPosition(TextTrack* aTextTrack) const {
HTMLTrackElement* trackElement = aTextTrack->GetTrackElement();
if (!trackElement) {
return -1;
}
return mMediaElement->IndexOf(trackElement);
}
bool
CompareTextTracks::Equals(TextTrack* aOne, TextTrack* aTwo) const {
// Two tracks can never be equal. If they have corresponding TrackElements
// they would need to occupy the same tree position (impossible) and in the
// case of tracks coming from AddTextTrack source we put the newest at the
// last position, so they won't be equal as well.
return false;
}
bool
CompareTextTracks::LessThan(TextTrack* aOne, TextTrack* aTwo) const
{
TextTrackSource sourceOne = aOne->GetTextTrackSource();
TextTrackSource sourceTwo = aTwo->GetTextTrackSource();
if (sourceOne != sourceTwo) {
return sourceOne == Track ||
(sourceOne == AddTextTrack && sourceTwo == MediaResourceSpecific);
}
switch (sourceOne) {
case Track: {
int32_t positionOne = TrackChildPosition(aOne);
int32_t positionTwo = TrackChildPosition(aTwo);
// If either position one or positiontwo are -1 then something has gone
// wrong. In this case we should just put them at the back of the list.
return positionOne != -1 && positionTwo != -1 &&
positionOne < positionTwo;
}
case AddTextTrack:
// For AddTextTrack sources the tracks will already be in the correct relative
// order in the source array. Assume we're called in iteration order and can
// therefore always report aOne < aTwo to maintain the original temporal ordering.
return true;
case MediaResourceSpecific:
// No rules for Media Resource Specific tracks yet.
break;
}
return true;
}
NS_IMPL_CYCLE_COLLECTION(TextTrackManager, mMediaElement, mTextTracks,
mPendingTextTracks, mNewCues)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TextTrackManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(TextTrackManager)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TextTrackManager)
StaticRefPtr<nsIWebVTTParserWrapper> TextTrackManager::sParserWrapper;
TextTrackManager::TextTrackManager(HTMLMediaElement *aMediaElement)
: mMediaElement(aMediaElement)
, performedTrackSelection(false)
{
nsISupports* parentObject =
mMediaElement->OwnerDoc()->GetParentObject();
NS_ENSURE_TRUE_VOID(parentObject);
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(parentObject);
mNewCues = new TextTrackCueList(window);
mTextTracks = new TextTrackList(window, this);
mPendingTextTracks = new TextTrackList(window, this);
if (!sParserWrapper) {
nsCOMPtr<nsIWebVTTParserWrapper> parserWrapper =
do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID);
sParserWrapper = parserWrapper;
ClearOnShutdown(&sParserWrapper);
}
}
TextTrackManager::~TextTrackManager()
{
}
TextTrackList*
TextTrackManager::GetTextTracks() const
{
return mTextTracks;
}
already_AddRefed<TextTrack>
TextTrackManager::AddTextTrack(TextTrackKind aKind, const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource)
{
if (!mMediaElement || !mTextTracks) {
return nullptr;
}
RefPtr<TextTrack> ttrack =
mTextTracks->AddTextTrack(aKind, aLabel, aLanguage, aMode, aReadyState,
aTextTrackSource, CompareTextTracks(mMediaElement));
AddCues(ttrack);
if (aTextTrackSource == Track) {
HonorUserPreferencesForTrackSelection();
}
return ttrack.forget();
}
void
TextTrackManager::AddTextTrack(TextTrack* aTextTrack)
{
if (!mMediaElement || !mTextTracks) {
return;
}
mTextTracks->AddTextTrack(aTextTrack, CompareTextTracks(mMediaElement));
AddCues(aTextTrack);
if (aTextTrack->GetTextTrackSource() == Track) {
HonorUserPreferencesForTrackSelection();
}
}
void
TextTrackManager::AddCues(TextTrack* aTextTrack)
{
if (!mNewCues) {
return;
}
TextTrackCueList* cueList = aTextTrack->GetCues();
if (cueList) {
bool dummy;
for (uint32_t i = 0; i < cueList->Length(); ++i) {
mNewCues->AddCue(*cueList->IndexedGetter(i, dummy));
}
}
}
void
TextTrackManager::RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly)
{
if (!mPendingTextTracks || !mTextTracks) {
return;
}
mPendingTextTracks->RemoveTextTrack(aTextTrack);
if (aPendingListOnly) {
return;
}
mTextTracks->RemoveTextTrack(aTextTrack);
}
void
TextTrackManager::DidSeek()
{
if (mTextTracks) {
mTextTracks->DidSeek();
}
}
void
TextTrackManager::UpdateCueDisplay()
{
if (!mMediaElement || !mTextTracks) {
return;
}
nsIFrame* frame = mMediaElement->GetPrimaryFrame();
nsVideoFrame* videoFrame = do_QueryFrame(frame);
if (!videoFrame) {
return;
}
nsCOMPtr<nsIContent> overlay = videoFrame->GetCaptionOverlay();
if (!overlay) {
return;
}
nsTArray<RefPtr<TextTrackCue> > activeCues;
mTextTracks->UpdateAndGetShowingCues(activeCues);
if (activeCues.Length() > 0) {
RefPtr<nsVariantCC> jsCues = new nsVariantCC();
jsCues->SetAsArray(nsIDataType::VTYPE_INTERFACE,
&NS_GET_IID(nsIDOMEventTarget),
activeCues.Length(),
static_cast<void*>(activeCues.Elements()));
nsPIDOMWindow* window = mMediaElement->OwnerDoc()->GetWindow();
if (window) {
sParserWrapper->ProcessCues(window, jsCues, overlay);
}
} else if (overlay->Length() > 0) {
nsContentUtils::SetNodeTextContent(overlay, EmptyString(), true);
}
}
void
TextTrackManager::AddCue(TextTrackCue& aCue)
{
if (mNewCues) {
mNewCues->AddCue(aCue);
}
}
void
TextTrackManager::PopulatePendingList()
{
if (!mTextTracks || !mPendingTextTracks || !mMediaElement) {
return;
}
uint32_t len = mTextTracks->Length();
bool dummy;
for (uint32_t index = 0; index < len; ++index) {
TextTrack* ttrack = mTextTracks->IndexedGetter(index, dummy);
if (ttrack && ttrack->Mode() != TextTrackMode::Disabled &&
ttrack->ReadyState() == TextTrackReadyState::Loading) {
mPendingTextTracks->AddTextTrack(ttrack,
CompareTextTracks(mMediaElement));
}
}
}
void
TextTrackManager::AddListeners()
{
if (mMediaElement) {
mMediaElement->AddEventListener(NS_LITERAL_STRING("resizevideocontrols"),
this, false, false);
}
}
void
TextTrackManager::HonorUserPreferencesForTrackSelection()
{
if (performedTrackSelection || !mTextTracks) {
return;
}
TextTrackKind ttKinds[] = { TextTrackKind::Captions,
TextTrackKind::Subtitles };
// Steps 1 - 3: Perform automatic track selection for different TextTrack
// Kinds.
PerformTrackSelection(ttKinds, ArrayLength(ttKinds));
PerformTrackSelection(TextTrackKind::Descriptions);
PerformTrackSelection(TextTrackKind::Chapters);
// Step 4: Set all TextTracks with a kind of metadata that are disabled
// to hidden.
for (uint32_t i = 0; i < mTextTracks->Length(); i++) {
TextTrack* track = (*mTextTracks)[i];
if (track->Kind() == TextTrackKind::Metadata && TrackIsDefault(track) &&
track->Mode() == TextTrackMode::Disabled) {
track->SetMode(TextTrackMode::Hidden);
}
}
performedTrackSelection = true;
}
bool
TextTrackManager::TrackIsDefault(TextTrack* aTextTrack)
{
HTMLTrackElement* trackElement = aTextTrack->GetTrackElement();
if (!trackElement) {
return false;
}
return trackElement->Default();
}
void
TextTrackManager::PerformTrackSelection(TextTrackKind aTextTrackKind)
{
TextTrackKind ttKinds[] = { aTextTrackKind };
PerformTrackSelection(ttKinds, ArrayLength(ttKinds));
}
void
TextTrackManager::PerformTrackSelection(TextTrackKind aTextTrackKinds[],
uint32_t size)
{
nsTArray<TextTrack*> candidates;
GetTextTracksOfKinds(aTextTrackKinds, size, candidates);
// Step 3: If any TextTracks in candidates are showing then abort these steps.
for (uint32_t i = 0; i < candidates.Length(); i++) {
if (candidates[i]->Mode() == TextTrackMode::Showing) {
return;
}
}
// Step 4: Honor user preferences for track selection, otherwise, set the
// first TextTrack in candidates with a default attribute to showing.
// TODO: Bug 981691 - Honor user preferences for text track selection.
for (uint32_t i = 0; i < candidates.Length(); i++) {
if (TrackIsDefault(candidates[i]) &&
candidates[i]->Mode() == TextTrackMode::Disabled) {
candidates[i]->SetMode(TextTrackMode::Showing);
return;
}
}
}
void
TextTrackManager::GetTextTracksOfKinds(TextTrackKind aTextTrackKinds[],
uint32_t size,
nsTArray<TextTrack*>& aTextTracks)
{
for (uint32_t i = 0; i < size; i++) {
GetTextTracksOfKind(aTextTrackKinds[i], aTextTracks);
}
}
void
TextTrackManager::GetTextTracksOfKind(TextTrackKind aTextTrackKind,
nsTArray<TextTrack*>& aTextTracks)
{
if (!mTextTracks) {
return;
}
for (uint32_t i = 0; i < mTextTracks->Length(); i++) {
TextTrack* textTrack = (*mTextTracks)[i];
if (textTrack->Kind() == aTextTrackKind) {
aTextTracks.AppendElement(textTrack);
}
}
}
NS_IMETHODIMP
TextTrackManager::HandleEvent(nsIDOMEvent* aEvent)
{
if (!mTextTracks) {
return NS_OK;
}
nsAutoString type;
aEvent->GetType(type);
if (type.EqualsLiteral("resizevideocontrols")) {
for (uint32_t i = 0; i< mTextTracks->Length(); i++) {
((*mTextTracks)[i])->SetCuesDirty();
}
}
return NS_OK;
}
} // namespace dom
} // namespace mozilla