Title: [146647] trunk/Source/WebCore
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);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to