CaptionUserPreferences should not be on the PageGroup if they are not really per...
[WebKit-https.git] / Source / WebCore / page / CaptionUserPreferences.cpp
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if ENABLE(VIDEO_TRACK)
29
30 #include "CaptionUserPreferences.h"
31
32 #include "HTMLMediaElement.h"
33 #include "Page.h"
34 #include "PageCache.h"
35 #include "Settings.h"
36 #include "TextTrackList.h"
37
38 namespace WebCore {
39
40 CaptionUserPreferences::CaptionUserPreferences()
41     : m_timer(this, &CaptionUserPreferences::timerFired)
42     , m_displayMode(ForcedOnly)
43     , m_testingMode(false)
44 {
45 }
46
47 CaptionUserPreferences::~CaptionUserPreferences()
48 {
49 }
50
51 void CaptionUserPreferences::timerFired(Timer<CaptionUserPreferences>&)
52 {
53     captionPreferencesChanged();
54 }
55
56 void CaptionUserPreferences::notify()
57 {
58     if (!m_timer.isActive())
59         m_timer.startOneShot(0);
60 }
61
62 CaptionUserPreferences::CaptionDisplayMode CaptionUserPreferences::captionDisplayMode() const
63 {
64     return m_displayMode;
65 }
66
67 void CaptionUserPreferences::setCaptionDisplayMode(CaptionUserPreferences::CaptionDisplayMode mode)
68 {
69     m_displayMode = mode;
70     notify();
71 }
72
73 bool CaptionUserPreferences::userPrefersCaptions(Document& document) const
74 {
75     Settings* settings = document.settings();
76     if (!settings)
77         return false;
78
79     return settings->shouldDisplayCaptions();
80 }
81
82 bool CaptionUserPreferences::userPrefersSubtitles(Document& document) const
83 {
84     Settings* settings = document.settings();
85     if (!settings)
86         return false;
87
88     return settings->shouldDisplaySubtitles();
89 }
90
91 bool CaptionUserPreferences::userPrefersTextDescriptions(Document& document) const
92 {
93     Settings* settings = document.settings();
94     if (!settings)
95         return false;
96
97     return settings->shouldDisplayTextDescriptions();
98 }
99
100 Vector<String> CaptionUserPreferences::preferredLanguages() const
101 {
102     Vector<String> languages = userPreferredLanguages();
103     if (m_testingMode && !m_userPreferredLanguage.isEmpty())
104         languages.insert(0, m_userPreferredLanguage);
105
106     return languages;
107 }
108
109 void CaptionUserPreferences::setPreferredLanguage(const String& language)
110 {
111     m_userPreferredLanguage = language;
112     notify();
113 }
114
115 static String trackDisplayName(TextTrack* track)
116 {
117     if (track == TextTrack::captionMenuOffItem())
118         return textTrackOffMenuItemText();
119     if (track == TextTrack::captionMenuAutomaticItem())
120         return textTrackAutomaticMenuItemText();
121
122     if (track->label().isEmpty() && track->language().isEmpty())
123         return textTrackNoLabelText();
124     if (!track->label().isEmpty())
125         return track->label();
126     return track->language();
127 }
128
129 String CaptionUserPreferences::displayNameForTrack(TextTrack* track) const
130 {
131     return trackDisplayName(track);
132 }
133     
134 Vector<RefPtr<TextTrack>> CaptionUserPreferences::sortedTrackListForMenu(TextTrackList* trackList)
135 {
136     ASSERT(trackList);
137
138     Vector<RefPtr<TextTrack>> tracksForMenu;
139
140     for (unsigned i = 0, length = trackList->length(); i < length; ++i) {
141         TextTrack* track = trackList->item(i);
142         const AtomicString& kind = track->kind();
143         if (kind == TextTrack::captionsKeyword() || kind == TextTrack::descriptionsKeyword() || kind == TextTrack::subtitlesKeyword())
144             tracksForMenu.append(track);
145     }
146
147     std::sort(tracksForMenu.begin(), tracksForMenu.end(), [](const RefPtr<TextTrack>& a, const RefPtr<TextTrack>& b) {
148         return codePointCompare(trackDisplayName(a.get()), trackDisplayName(b.get())) < 0;
149     });
150
151     tracksForMenu.insert(0, TextTrack::captionMenuOffItem());
152     tracksForMenu.insert(1, TextTrack::captionMenuAutomaticItem());
153
154     return tracksForMenu;
155 }
156
157 int CaptionUserPreferences::textTrackSelectionScore(TextTrack* track, HTMLMediaElement* element) const
158 {
159     int trackScore = 0;
160
161     if (track->kind() != TextTrack::captionsKeyword() && track->kind() != TextTrack::subtitlesKeyword())
162         return trackScore;
163     
164     if (!userPrefersSubtitles(element->document()) && !userPrefersCaptions(element->document()))
165         return trackScore;
166     
167     if (track->kind() == TextTrack::subtitlesKeyword() && userPrefersSubtitles(element->document()))
168         trackScore = 1;
169     else if (track->kind() == TextTrack::captionsKeyword() && userPrefersCaptions(element->document()))
170         trackScore = 1;
171     
172     return trackScore + textTrackLanguageSelectionScore(track, preferredLanguages());
173 }
174
175 int CaptionUserPreferences::textTrackLanguageSelectionScore(TextTrack* track, const Vector<String>& preferredLanguages) const
176 {
177     if (track->language().isEmpty())
178         return 0;
179
180     size_t languageMatchIndex = indexOfBestMatchingLanguageInList(track->language(), preferredLanguages);
181     if (languageMatchIndex >= preferredLanguages.size())
182         return 0;
183
184     // Matching a track language is more important than matching track type, so this multiplier must be
185     // greater than the maximum value returned by textTrackSelectionScore.
186     return (preferredLanguages.size() - languageMatchIndex) * 10;
187 }
188
189 String CaptionUserPreferences::captionsStyleSheet()
190 {
191     if (!m_captionsStyleSheetOverride.isEmpty() || testingMode())
192         return m_captionsStyleSheetOverride;
193
194     return platformCaptionsStyleSheet();
195 }
196
197 void CaptionUserPreferences::setCaptionsStyleSheetOverride(const String& override)
198 {
199     m_captionsStyleSheetOverride = override;
200     captionPreferencesChanged();
201 }
202
203 String CaptionUserPreferences::captionsStyleSheetOverride() const
204 {
205     return m_captionsStyleSheetOverride;
206 }
207
208 String CaptionUserPreferences::primaryAudioTrackLanguageOverride() const
209 {
210     if (!m_primaryAudioTrackLanguageOverride.isEmpty())
211         return m_primaryAudioTrackLanguageOverride;
212     return defaultLanguage();
213 }
214
215 void CaptionUserPreferences::captionPreferencesChanged()
216 {
217     Page::updateStyleForAllPagesForCaptionPreferencesChanged();
218     pageCache()->markPagesForCaptionPreferencesChanged();
219 }
220
221 } // namespace WebCore
222
223 #endif // ENABLE(VIDEO_TRACK)