- Revision
- 146647
- Author
- [email protected]
- Date
- 2013-03-22 13:24:35 -0700 (Fri, 22 Mar 2013)
Log Message
Cleanup text track selection logic
https://bugs.webkit.org/show_bug.cgi?id=113062
Reviewed by Jer Noble.
No new tests, covered by existing tests.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::userIsInterestedInThisTrackKind): Remove.
(WebCore::HTMLMediaElement::configureTextTrackGroup): Don't look at track attributes directly,
use captionPreferences->textTrackSelectionScore to calculate track rank.
(WebCore::HTMLMediaElement::setClosedCaptionsVisible): Set m_processingPreferenceChange here
instead of in captionPreferencesChanged.
(WebCore::HTMLMediaElement::captionPreferencesChanged): Don't suppress calls to setClosedCaptionsVisible,
existing code already makes sure we don't do unnecessary work.
* html/HTMLMediaElement.h:
* html/shadow/MediaControlElements.cpp:
(WebCore::MediaControlTextTrackContainerElement::updateDisplay): Drive by cleanup, don't
process inactive cues.
* html/shadow/MediaControlsApple.cpp:
(WebCore::MediaControlsApple::changedClosedCaptionsVisibility): Call resetTrackListMenu instead
of updateDisplay so we only mark the menu as needing a recalculation and do the work when
it is displayed.
* page/CaptionUserPreferences.cpp:
(WebCore::CaptionUserPreferences::shouldShowCaptions): When in testing mode, return true if
the caption or subtitle preference has been set.
(WebCore::CaptionUserPreferences::setShouldShowCaptions): In testing mode, clear the caption
and subtitle preference when passed false.
(WebCore::CaptionUserPreferences::textTrackSelectionScore): Calculate the track score based on
track type preference and preferred language.
(WebCore::CaptionUserPreferences::textTrackLanguageSelectionScore): Score a track according to
the language presence and position in the preferred languages list.
* page/CaptionUserPreferences.h:
* page/CaptionUserPreferencesMac.h:
* page/CaptionUserPreferencesMac.mm:
(WebCore::CaptionUserPreferencesMac::textTrackSelectionScore): Calculate track language score
according to user preferences.
* platform/Language.cpp:
(WebCore::indexOfBestMatchingLanguageInList): Repurposed the static bestMatchingLanguage
function to return the location of a language in a Vector.
(WebCore::preferredLanguageFromList): Removed.
* platform/Language.h:
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (146646 => 146647)
--- trunk/Source/WebCore/ChangeLog 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/ChangeLog 2013-03-22 20:24:35 UTC (rev 146647)
@@ -1,3 +1,53 @@
+2013-03-22 Eric Carlson <[email protected]>
+
+ Cleanup text track selection logic
+ https://bugs.webkit.org/show_bug.cgi?id=113062
+
+ Reviewed by Jer Noble.
+
+ No new tests, covered by existing tests.
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::userIsInterestedInThisTrackKind): Remove.
+ (WebCore::HTMLMediaElement::configureTextTrackGroup): Don't look at track attributes directly,
+ use captionPreferences->textTrackSelectionScore to calculate track rank.
+ (WebCore::HTMLMediaElement::setClosedCaptionsVisible): Set m_processingPreferenceChange here
+ instead of in captionPreferencesChanged.
+ (WebCore::HTMLMediaElement::captionPreferencesChanged): Don't suppress calls to setClosedCaptionsVisible,
+ existing code already makes sure we don't do unnecessary work.
+ * html/HTMLMediaElement.h:
+
+ * html/shadow/MediaControlElements.cpp:
+ (WebCore::MediaControlTextTrackContainerElement::updateDisplay): Drive by cleanup, don't
+ process inactive cues.
+
+ * html/shadow/MediaControlsApple.cpp:
+ (WebCore::MediaControlsApple::changedClosedCaptionsVisibility): Call resetTrackListMenu instead
+ of updateDisplay so we only mark the menu as needing a recalculation and do the work when
+ it is displayed.
+
+ * page/CaptionUserPreferences.cpp:
+ (WebCore::CaptionUserPreferences::shouldShowCaptions): When in testing mode, return true if
+ the caption or subtitle preference has been set.
+ (WebCore::CaptionUserPreferences::setShouldShowCaptions): In testing mode, clear the caption
+ and subtitle preference when passed false.
+ (WebCore::CaptionUserPreferences::textTrackSelectionScore): Calculate the track score based on
+ track type preference and preferred language.
+ (WebCore::CaptionUserPreferences::textTrackLanguageSelectionScore): Score a track according to
+ the language presence and position in the preferred languages list.
+ * page/CaptionUserPreferences.h:
+
+ * page/CaptionUserPreferencesMac.h:
+ * page/CaptionUserPreferencesMac.mm:
+ (WebCore::CaptionUserPreferencesMac::textTrackSelectionScore): Calculate track language score
+ according to user preferences.
+
+ * platform/Language.cpp:
+ (WebCore::indexOfBestMatchingLanguageInList): Repurposed the static bestMatchingLanguage
+ function to return the location of a language in a Vector.
+ (WebCore::preferredLanguageFromList): Removed.
+ * platform/Language.h:
+
2013-03-22 ChangSeok Oh <[email protected]>
Build fix for TransformationMatrix
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (146646 => 146647)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2013-03-22 20:24:35 UTC (rev 146647)
@@ -3079,59 +3079,27 @@
return captionPreferences->userHasCaptionPreferences() && captionPreferences->shouldShowCaptions();
}
-bool HTMLMediaElement::userIsInterestedInThisTrackKind(String kind) const
-{
- if (m_disableCaptions)
- return false;
-
- Page* page = document()->page();
- if (!page)
- return false;
-
- CaptionUserPreferences* captionPreferences = page->group().captionPreferences();
- bool userPrefersCaptionsOrSubtitles = m_closedCaptionsVisible || userPrefersCaptions();
-
- if (kind == TextTrack::subtitlesKeyword())
- return captionPreferences->userPrefersSubtitles() || userPrefersCaptionsOrSubtitles;
- if (kind == TextTrack::captionsKeyword())
- return captionPreferences->userPrefersCaptions() || userPrefersCaptionsOrSubtitles;
- if (kind == TextTrack::descriptionsKeyword())
- return captionPreferences->userPrefersTextDescriptions() || userPrefersCaptionsOrSubtitles;
-
- return false;
-}
-
void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group)
{
ASSERT(group.tracks.size());
- String bestMatchingLanguage;
- if (group.hasSrcLang && document()->page()) {
- Vector<String> trackLanguages;
- trackLanguages.reserveInitialCapacity(group.tracks.size());
- for (size_t i = 0; i < group.tracks.size(); ++i) {
- String srcLanguage = group.tracks[i]->language();
- if (srcLanguage.length())
- trackLanguages.append(srcLanguage);
- }
- bestMatchingLanguage = preferredLanguageFromList(trackLanguages, document()->page()->group().captionPreferences()->preferredLanguages());
- }
+ Page* page = document()->page();
+ CaptionUserPreferences* captionPreferences = page? page->group().captionPreferences() : 0;
// First, find the track in the group that should be enabled (if any).
Vector<RefPtr<TextTrack> > currentlyEnabledTracks;
RefPtr<TextTrack> trackToEnable;
RefPtr<TextTrack> defaultTrack;
RefPtr<TextTrack> fallbackTrack;
+ int highestTrackScore = 0;
for (size_t i = 0; i < group.tracks.size(); ++i) {
RefPtr<TextTrack> textTrack = group.tracks[i];
if (m_processingPreferenceChange && textTrack->mode() == TextTrack::showingKeyword())
currentlyEnabledTracks.append(textTrack);
- if (trackToEnable)
- continue;
-
- if (userIsInterestedInThisTrackKind(textTrack->kind())) {
+ int trackScore = captionPreferences ? captionPreferences->textTrackSelectionScore(textTrack.get()) : 0;
+ if (trackScore) {
// * If the text track kind is { [subtitles or captions] [descriptions] } and the user has indicated an interest in having a
// track with this text track kind, text track language, and text track label enabled, and there is no
// other text track in the media element's list of text tracks with a text track kind of either subtitles
@@ -3141,17 +3109,14 @@
// to believe is appropriate for the user, and there is no other text track in the media element's list of
// text tracks with a text track kind of chapters whose text track mode is showing
// Let the text track mode be showing.
- if (bestMatchingLanguage.length()) {
- if (textTrack->language() == bestMatchingLanguage)
- trackToEnable = textTrack;
- } else if (textTrack->isDefault()) {
- // The user is interested in this type of track, but their language preference doesn't match any track so we will
- // enable the 'default' track.
- defaultTrack = textTrack;
+ if (trackScore > highestTrackScore) {
+ highestTrackScore = trackScore;
+ trackToEnable = textTrack;
}
- // Remember the first track that doesn't match language or have 'default' to potentially use as fallback.
- if (!fallbackTrack)
+ if (!defaultTrack && textTrack->isDefault())
+ defaultTrack = textTrack;
+ if (!defaultTrack && !fallbackTrack)
fallbackTrack = textTrack;
} else if (!group.visibleTrack && !defaultTrack && textTrack->isDefault()) {
// * If the track element has a default attribute specified, and there is no other text track in the media
@@ -4328,6 +4293,7 @@
#if ENABLE(VIDEO_TRACK)
if (RuntimeEnabledFeatures::webkitVideoTrackEnabled()) {
+ m_processingPreferenceChange = true;
m_disableCaptions = !m_closedCaptionsVisible;
markCaptionAndSubtitleTracksAsUnconfigured();
@@ -4529,12 +4495,7 @@
if (hasMediaControls())
mediaControls()->textTrackPreferencesChanged();
- bool prefersCaptions = userPrefersCaptions();
- if (m_disableCaptions == !prefersCaptions)
- return;
-
- m_processingPreferenceChange = true;
- setClosedCaptionsVisible(prefersCaptions);
+ setClosedCaptionsVisible(userPrefersCaptions());
}
void HTMLMediaElement::markCaptionAndSubtitleTracksAsUnconfigured()
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (146646 => 146647)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2013-03-22 20:24:35 UTC (rev 146647)
@@ -272,7 +272,6 @@
static int textTracksIndexNotFound() { return -2; }
bool userPrefersCaptions() const;
- bool userIsInterestedInThisTrackKind(String) const;
bool textTracksAreReady() const;
void configureTextTrackDisplay();
void updateTextTrackDisplay();
Modified: trunk/Source/WebCore/html/shadow/MediaControlElements.cpp (146646 => 146647)
--- trunk/Source/WebCore/html/shadow/MediaControlElements.cpp 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/html/shadow/MediaControlElements.cpp 2013-03-22 20:24:35 UTC (rev 146647)
@@ -1254,7 +1254,7 @@
TextTrackCue* cue = activeCues[i].data();
ASSERT(cue->isActive());
- if (!cue->track() || !cue->track()->isRendered())
+ if (!cue->track() || !cue->track()->isRendered() || !cue->isActive())
continue;
RefPtr<TextTrackCueBox> displayBox = cue->getDisplayTree(m_videoDisplaySize.size());
Modified: trunk/Source/WebCore/html/shadow/MediaControlsApple.cpp (146646 => 146647)
--- trunk/Source/WebCore/html/shadow/MediaControlsApple.cpp 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/html/shadow/MediaControlsApple.cpp 2013-03-22 20:24:35 UTC (rev 146647)
@@ -306,7 +306,7 @@
{
MediaControls::changedClosedCaptionsVisibility();
if (m_closedCaptionsTrackList)
- m_closedCaptionsTrackList->updateDisplay();
+ m_closedCaptionsTrackList->resetTrackListMenu();
}
void MediaControlsApple::reset()
Modified: trunk/Source/WebCore/page/CaptionUserPreferences.cpp (146646 => 146647)
--- trunk/Source/WebCore/page/CaptionUserPreferences.cpp 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/page/CaptionUserPreferences.cpp 2013-03-22 20:24:35 UTC (rev 146647)
@@ -51,7 +51,10 @@
bool CaptionUserPreferences::shouldShowCaptions() const
{
- return m_testingMode ? m_shouldShowCaptions : false;
+ if (!m_testingMode)
+ return false;
+
+ return m_shouldShowCaptions || userPrefersCaptions() || userPrefersSubtitles();
}
void CaptionUserPreferences::timerFired(Timer<CaptionUserPreferences>*)
@@ -72,6 +75,10 @@
void CaptionUserPreferences::setShouldShowCaptions(bool preference)
{
m_shouldShowCaptions = preference;
+ if (m_testingMode && !preference) {
+ setUserPrefersCaptions(false);
+ setUserPrefersSubtitles(false);
+ }
notify();
}
@@ -185,6 +192,36 @@
return tracksForMenu;
}
+int CaptionUserPreferences::textTrackSelectionScore(TextTrack* track) const
+{
+ int trackScore = 0;
+
+ if (track->kind() != TextTrack::captionsKeyword() && track->kind() != TextTrack::subtitlesKeyword())
+ return trackScore;
+
+ if (track->kind() == TextTrack::subtitlesKeyword() && userPrefersSubtitles())
+ trackScore = 1;
+ else if (track->kind() == TextTrack::captionsKeyword() && userPrefersCaptions())
+ trackScore = 1;
+
+ return trackScore + textTrackLanguageSelectionScore(track);
}
+int CaptionUserPreferences::textTrackLanguageSelectionScore(TextTrack* track) const
+{
+ if (track->language().isEmpty())
+ return 0;
+
+ Vector<String> languages = preferredLanguages();
+ size_t languageMatchIndex = indexOfBestMatchingLanguageInList(track->language(), languages);
+ if (languageMatchIndex >= languages.size())
+ return 0;
+
+ // Matching a track language is more important than matching track type, so this multiplier must be
+ // greater than the maximum value returned by textTrackSelectionScore.
+ return (languages.size() - languageMatchIndex) * 10;
+}
+
+}
+
#endif // ENABLE(VIDEO_TRACK)
Modified: trunk/Source/WebCore/page/CaptionUserPreferences.h (146646 => 146647)
--- trunk/Source/WebCore/page/CaptionUserPreferences.h 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/page/CaptionUserPreferences.h 2013-03-22 20:24:35 UTC (rev 146647)
@@ -49,6 +49,9 @@
virtual bool shouldShowCaptions() const;
virtual void setShouldShowCaptions(bool);
+ virtual int textTrackSelectionScore(TextTrack*) const;
+ virtual int textTrackLanguageSelectionScore(TextTrack*) const;
+
virtual bool userPrefersCaptions() const;
virtual void setUserPrefersCaptions(bool);
Modified: trunk/Source/WebCore/page/CaptionUserPreferencesMac.h (146646 => 146647)
--- trunk/Source/WebCore/page/CaptionUserPreferencesMac.h 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/page/CaptionUserPreferencesMac.h 2013-03-22 20:24:35 UTC (rev 146647)
@@ -60,6 +60,7 @@
#endif
+ virtual int textTrackSelectionScore(TextTrack*) const OVERRIDE;
virtual Vector<RefPtr<TextTrack> > sortedTrackListForMenu(TextTrackList*) OVERRIDE;
virtual String displayNameForTrack(TextTrack*) const OVERRIDE;
Modified: trunk/Source/WebCore/page/CaptionUserPreferencesMac.mm (146646 => 146647)
--- trunk/Source/WebCore/page/CaptionUserPreferencesMac.mm 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/page/CaptionUserPreferencesMac.mm 2013-03-22 20:24:35 UTC (rev 146647)
@@ -598,6 +598,40 @@
return lowercaseLanguageCode;
}
+int CaptionUserPreferencesMac::textTrackSelectionScore(TextTrack* track) const
+{
+ if (!shouldShowCaptions())
+ return 0;
+ if (track->kind() != TextTrack::captionsKeyword() && track->kind() != TextTrack::subtitlesKeyword())
+ return 0;
+ if (track->containsOnlyForcedSubtitles())
+ return 0;
+ if (!track->isMainProgramContent())
+ return 0;
+
+ int trackScore = 0;
+
+ if (userPrefersCaptions()) {
+ // When the user prefers accessiblity tracks, rank is SDH, then CC, then subtitles.
+ if (track->kind() == track->subtitlesKeyword())
+ trackScore = 1;
+ else if (track->isClosedCaptions())
+ trackScore = 2;
+ else
+ trackScore = 3;
+ } else {
+ // When the user prefers translation tracks, rank is subtitles, then SDH, then CC tracks.
+ if (track->kind() == track->subtitlesKeyword())
+ trackScore = 3;
+ else if (!track->isClosedCaptions())
+ trackScore = 2;
+ else
+ trackScore = 1;
+ }
+
+ return trackScore + textTrackLanguageSelectionScore(track);
+}
+
static bool textTrackCompare(const RefPtr<TextTrack>& a, const RefPtr<TextTrack>& b)
{
String preferredLanguageDisplayName = displayNameForLanguageLocale(languageIdentifier(defaultLanguage()));
Modified: trunk/Source/WebCore/platform/Language.cpp (146646 => 146647)
--- trunk/Source/WebCore/platform/Language.cpp 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/platform/Language.cpp 2013-03-22 20:24:35 UTC (rev 146647)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -105,50 +105,44 @@
return lowercaseLanguageCode;
}
-static String bestMatchingLanguage(const String& language, const Vector<String>& languageList)
+size_t indexOfBestMatchingLanguageInList(const String& language, const Vector<String>& languageList)
{
- bool canMatchLanguageOnly = (language.length() == 2 || (language.length() >= 3 && language[2] == '-'));
String languageWithoutLocaleMatch;
String languageMatchButNotLocale;
+ size_t languageWithoutLocaleMatchIndex = 0;
+ size_t languageMatchButNotLocaleMatchIndex = 0;
+ bool canMatchLanguageOnly = (language.length() == 2 || (language.length() >= 3 && language[2] == '-'));
for (size_t i = 0; i < languageList.size(); ++i) {
String canonicalizedLanguageFromList = canonicalLanguageIdentifier(languageList[i]);
if (language == canonicalizedLanguageFromList)
- return languageList[i];
+ return i;
if (canMatchLanguageOnly && canonicalizedLanguageFromList.length() >= 2) {
if (language[0] == canonicalizedLanguageFromList[0] && language[1] == canonicalizedLanguageFromList[1]) {
- if (!languageWithoutLocaleMatch.length() && canonicalizedLanguageFromList.length() == 2)
+ if (!languageWithoutLocaleMatch.length() && canonicalizedLanguageFromList.length() == 2) {
languageWithoutLocaleMatch = languageList[i];
- if (!languageMatchButNotLocale.length() && canonicalizedLanguageFromList.length() >= 3)
+ languageWithoutLocaleMatchIndex = i;
+ }
+ if (!languageMatchButNotLocale.length() && canonicalizedLanguageFromList.length() >= 3) {
languageMatchButNotLocale = languageList[i];
+ languageMatchButNotLocaleMatchIndex = i;
+ }
}
}
}
- // If we have both a language-only match and a languge-but-not-locale match, return the
+ // If we have both a language-only match and a languge-but-not-locale match, return the
// languge-only match as is considered a "better" match. For example, if the list
// provided has both "en-GB" and "en" and the user prefers "en-US" we will return "en".
if (languageWithoutLocaleMatch.length())
- return languageWithoutLocaleMatch;
+ return languageWithoutLocaleMatchIndex;
if (languageMatchButNotLocale.length())
- return languageMatchButNotLocale;
-
- return emptyString();
-}
+ return languageMatchButNotLocaleMatchIndex;
-String preferredLanguageFromList(const Vector<String>& languageList, const Vector<String> preferredLanguages)
-{
- for (size_t i = 0; i < preferredLanguages.size(); ++i) {
- String bestMatch = bestMatchingLanguage(canonicalLanguageIdentifier(preferredLanguages[i]), languageList);
-
- if (bestMatch.length())
- return bestMatch;
- }
-
- return emptyString();
+ return languageList.size();
}
String displayNameForLanguageLocale(const String& localeName)
Modified: trunk/Source/WebCore/platform/Language.h (146646 => 146647)
--- trunk/Source/WebCore/platform/Language.h 2013-03-22 20:16:49 UTC (rev 146646)
+++ trunk/Source/WebCore/platform/Language.h 2013-03-22 20:24:35 UTC (rev 146647)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2010, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,7 +35,7 @@
Vector<String> userPreferredLanguages();
Vector<String> userPreferredLanguagesOverride();
void overrideUserPreferredLanguages(const Vector<String>&);
-String preferredLanguageFromList(const Vector<String>& languageList, const Vector<String> preferredLanguages);
+size_t indexOfBestMatchingLanguageInList(const String& language, const Vector<String>& languageList);
// The observer function will be called when system language changes.
typedef void (*LanguageChangeObserverFunction)(void* context);